Как скопировать статические файлы для создания каталога с помощью Webpack?
Я пытаюсь уйти от Gulp
в Webpack
, В Gulp
У меня есть задача, которая копирует все файлы и папки из / static / folder в / build / folder. Как сделать то же самое с Webpack
? Нужен ли мне какой-нибудь плагин?
13 ответов
Вам не нужно копировать вещи, веб-пакет работает иначе, чем gulp. Webpack - это пакет модулей, и все, на что вы ссылаетесь в своих файлах, будет включено. Вам просто нужно указать загрузчик для этого.
Так что если вы напишите:
var myImage = require("./static/myImage.jpg");
Сначала Webpack попытается проанализировать указанный файл как JavaScript (потому что это по умолчанию). Конечно, это не удастся. Вот почему вам нужно указать загрузчик для этого типа файла. Файл- или, например, url-загрузчик, берет указанный файл, помещает его в выходную папку веб-пакета (который должен быть build
в вашем случае) и верните хешированный URL для этого файла.
var myImage = require("./static/myImage.jpg");
console.log(myImage); // '/build/12as7f9asfasgasg.jpg'
Обычно загрузчики применяются через конфигурацию webpack:
// webpack.config.js
module.exports = {
...
module: {
loaders: [
{ test: /\.(jpe?g|gif|png|svg|woff|ttf|wav|mp3)$/, loader: "file" }
]
}
};
Конечно, вам нужно сначала установить загрузчик файлов, чтобы это работало.
Требование ресурсов с помощью модуля загрузчика файлов - это способ использования веб-пакета ( источник). Однако, если вам нужна большая гибкость или вы хотите более чистый интерфейс, вы также можете копировать статические файлы напрямую, используя мой copy-webpack-plugin
( нпм, Github). Для тебя static
в build
пример:
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
context: path.join(__dirname, 'your-app'),
plugins: [
new CopyWebpackPlugin([
{ from: 'static' }
])
]
};
Если вы хотите скопировать ваши статические файлы, вы можете использовать загрузчик файлов следующим образом:
для HTML-файлов:
в webpack.config.js:
module.exports = {
...
module: {
loaders: [
{ test: /\.(html)$/,
loader: "file?name=[path][name].[ext]&context=./app/static"
}
]
}
};
в вашем файле js:
require.context("./static/", true, /^\.\/.*\.html/);
./static/ относительно того, где находится ваш файл js.
Вы можете сделать то же самое с изображениями или чем-то еще. Контекст является мощным методом для изучения!
Одно преимущество, которое приносит вышеупомянутый copy-webpack-plugin, которое не было объяснено ранее, состоит в том, что все другие методы, упомянутые здесь, все еще связывают ресурсы в ваши файлы комплекта (и требуют, чтобы вы "требовали" или "импортировали" их где-то). Если я просто хочу переместить некоторые изображения или некоторые шаблоны, я не хочу загромождать свой файл комплекта javascript бесполезными ссылками на них, я просто хочу, чтобы файлы выводились в нужном месте. Я не нашел другого способа сделать это в веб-пакете. По общему признанию это не то, для чего первоначально был разработан веб-пакет, но это определенно текущий случай использования. (@BreakDS Я надеюсь, что это отвечает на ваш вопрос - это только выгода, если вы этого хотите)
Webpack 5 добавляет модули ресурсов, которые по сути являются заменой распространенных загрузчиков файлов. Я скопировал соответствующую часть документации ниже:
-
asset/resource
генерирует отдельный файл и экспортирует URL. Ранее можно было использоватьfile-loader
. -
asset/inline
экспортирует URI данных актива. Ранее это было возможно при использовании. -
asset/source
экспортирует исходный код актива. Ранее можно было использоватьraw-loader
. -
asset
автоматически выбирает между экспортом URI данных и созданием отдельного файла. Ранее можно было использоватьurl-loader
с ограничением размера актива.
Вы можете сделать так, чтобы ваша конфигурация выглядела так:
// webpack.config.js
module.exports = {
...
module: {
loaders: [
{
test: /\.(jpe?g|gif|png|svg|woff|ttf|wav|mp3)$/,
type: "asset/resource"
}
]
}
};
Вы можете управлять копированием файлов, используя шаблонные пути . Для шаблона по умолчанию для всех ресурсов вы можете сделать что-то вроде этого:
// webpack.config.js
module.exports = {
...
output: {
...
assetModuleFilename: '[path][name].[hash][ext][query]'
}
}
Для определенного набора ресурсов вам нужно сделать следующее:
// webpack.config.js
module.exports = {
...
module: {
loaders: [
{
test: /\.(jpe?g|gif|png|svg|woff|ttf|wav|mp3)$/,
type: "asset/resource"
generator: {
filename: '[path][name].[hash][ext][query]'
}
}
]
}
};
В обоих случаях имена файлов будут выглядеть как
build/images/img.151cfcfa1bd74779aadb.png
. Измените шаблон в соответствии с вашим вариантом использования.
То, как я загружаю статический images
а также fonts
:
module: {
rules: [
....
{
test: /\.(jpe?g|png|gif|svg)$/i,
/* Exclude fonts while working with images, e.g. .svg can be both image or font. */
exclude: path.resolve(__dirname, '../src/assets/fonts'),
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
}]
},
{
test: /\.(woff(2)?|ttf|eot|svg|otf)(\?v=\d+\.\d+\.\d+)?$/,
/* Exclude images while working with fonts, e.g. .svg can be both image or font. */
exclude: path.resolve(__dirname, '../src/assets/images'),
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
},
}
]
}
Не забудьте установить file-loader
чтобы это работало.
Выше предложения хороши. Но чтобы попытаться ответить на ваш вопрос напрямую, я бы предложил использовать cpy-cli
в сценарии, определенном в вашем package.json
,
Этот пример ожидает node
где-то на вашем пути. устанавливать cpy-cli
как зависимость развития:
npm install --save-dev cpy-cli
Затем создайте пару файлов nodejs. Один, чтобы сделать копию, а другой, чтобы отобразить галочку и сообщение.
copy.js
#!/usr/bin/env node
var shelljs = require('shelljs');
var addCheckMark = require('./helpers/checkmark');
var path = require('path');
var cpy = path.join(__dirname, '../node_modules/cpy-cli/cli.js');
shelljs.exec(cpy + ' /static/* /build/', addCheckMark.bind(null, callback));
function callback() {
process.stdout.write(' Copied /static/* to the /build/ directory\n\n');
}
checkmark.js
var chalk = require('chalk');
/**
* Adds mark check symbol
*/
function addCheckMark(callback) {
process.stdout.write(chalk.green(' ✓'));
callback();
}
module.exports = addCheckMark;
Добавьте скрипт в package.json
, Предполагая, что скрипты находятся в <project-root>/scripts/
...
"scripts": {
"copy": "node scripts/copy.js",
...
Чтобы запустить скрипт:
npm run copy
Вы можете написать bash в вашем package.json:
# package.json
{
"name": ...,
"version": ...,
"scripts": {
"build": "NODE_ENV=production npm run webpack && cp -v <this> <that> && echo ok",
...
}
}
Скорее всего, вы должны использовать CopyWebpackPlugin, который был упомянут в ответе kevlened. В качестве альтернативы для некоторых файлов, таких как .html или .json, вы также можете использовать raw-loader или json-loader. Установите его через npm install -D raw-loader
и тогда вам нужно только добавить еще один загрузчик в наш webpack.config.js
файл.
Подобно:
{
test: /\.html/,
loader: 'raw'
}
Примечание. Перезапустите webpack-dev-server, чтобы изменения в конфигурации вступили в силу.
И теперь вы можете запрашивать HTML-файлы, используя относительные пути, это значительно упрощает перемещение папок.
template: require('./nav.html')
Файл конфигурации веб-пакета (в веб-пакете 2) позволяет экспортировать цепочку обещаний, если последний шаг возвращает объект конфигурации веб-пакета. Смотрите документацию по конфигурации обещаний. Оттуда:
Webpack теперь поддерживает возврат Promise из файла конфигурации. Это позволяет выполнять асинхронную обработку в вашем файле конфигурации.
Вы можете создать простую функцию рекурсивного копирования, которая копирует ваш файл, и только после этого запускает веб-пакет. Например:
module.exports = function(){
return copyTheFiles( inpath, outpath).then( result => {
return { entry: "..." } // Etc etc
} )
}
Я тоже застрял здесь. copy-webpack-plugin работал для меня.
Тем не менее, "copy-webpack-plugin" не был необходим в моем случае (я узнал позже).
веб-пакет игнорирует корневые пути
пример
<img src="/images/logo.png'>
Следовательно, чтобы сделать это без использования 'copy-webpack-plugin', используйте '~' в путях
<img src="~images/logo.png'>
"~" указывает веб-пакету рассматривать "изображения" как модуль
примечание: вам может понадобиться добавить родительский каталог к каталогу изображений в
resolve: {
modules: [
'parent-directory of images',
'node_modules'
]
}
Посетите https://vuejs-templates.github.io/webpack/static.html
Скажем, все ваши статические ресурсы находятся в папке "static" на корневом уровне, и вы хотите скопировать их в папку сборки, сохраняя структуру подпапки, а затем в ваш файл ввода) просто поместите
//index.js or index.jsx
require.context("!!file?name=[path][name].[ext]&context=./static!../static/", true, /^\.\/.*\.*/);
В моем случае я использовал webpack для плагина wordpress для сжатия файлов js, где файлы плагина уже сжаты и их нужно пропустить из процесса.
optimization: {
minimize: false,
},
externals: {
"jquery": "jQuery",
},
entry: glob.sync('./js/plugin/**.js').reduce(function (obj, el) {
obj[path.parse(el).name] = el;
return obj
}, {}),
output: {
path: path.resolve(__dirname, './js/dist/plugin'),
filename: "[name].js",
clean: true,
},
Это использовалось для копирования файла js в папку сборки. Использование любых других методов, таких как file-loader и copy-webpack, создает проблемы с этим.
Надеюсь, это поможет кому-то.