Как скопировать статические файлы для создания каталога с помощью 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, создает проблемы с этим.

Надеюсь, это поможет кому-то.

Другие вопросы по тегам