понедельник, 26 февраля 2018 г.

Webpack 4 - Краткий конфиг с комментариями

Файл webpack.config.js

const webpack = require('webpack') // Загружаем Webpack для использования встроенных в него плагинов.
        , CleanWebpackPlugin = require('clean-webpack-plugin')
        , ExtractWebpackTextPlugin = require("extract-text-webpack-plugin") // Загружаем отдельный плагин для Webpack, установленный через NPM.
        , path = require('path'); // Загружаем модуль "path" для прописывания абсолютных путей от диска "C" до файлов.

module.exports = [ // Webpack может принимать массив конфигов и выполнять их все сразу.
    { // Конфиг сборки Webpack.

        // Входные файлы для сборки.
    /*
          entry: path.resolve(__dirname, 'src/polyfills.js') // Одиночный стартовый файл, который будет помещен в итоговый файл. Имя выходного файла будет main.js, если задан output.filename: '[name].js'
    */

          entry: { // Набор входных файлов, помещаемых в итоговый файл сборки и выполняемых в нём согласно порядку их следования в этом массиве.
              'bundle': [ // Имя выходного файла сборки, если задан output.filename: '[name].js'
                  path.resolve(__dirname, 'src/polyfills.js') // Файл с полифилами помещается в итоговый файл сборки первым и выполняется в нём первым.
                , path.resolve(__dirname, 'src/vendors.js') // Файл с вендорами помещается в итоговый файл сборки вторым и выполняется в нём вторым.
                , path.resolve(__dirname, 'src/index.js') // Главный стартовый файл помещается в итоговый файл сборки третьим и выполняется в нём третьим.
              ]
          }

    /*
          entry: { // Набор отдельных входных файлов, помещаемых в такие же отдельные выходные файлы с теми же именами. Обязательно должен быть задан output.filename: '[name].js'
              'polyfills': path.resolve(__dirname, 'src/polyfills.js') // Отдельный входной файл.
            , 'vendors': path.resolve(__dirname, 'src/vendors.js') // Отдельный входной файл.
            , 'index': path.resolve(__dirname, 'src/index.js') // Отдельный входной файл.
          }
    */
        // Итоговые файлы сборки.
        , output: { // Описание итогового файла сборки.
              path: path.resolve(__dirname, 'dist') // В какую папку записать итоговые файлы сборки, картинки и CSS-файлы.
             , filename: 'bundle.js' // Если написано так, то все входные файлы из массива или одиночный входной файл будут помещены в один общий итоговый файл с данным именем.
            // , filename: '[name].js' // Если написано так, то исходные файлы передаются по отдельности и итоговых файлов сборки будет несколько.
            // Из каждого файла объекта "entry" будет сформирован отдельный итоговый файл, согласно его названию:
            // dist/polyfills.js
            // dist/vendor.js
            // dist/index.js
            // При этом каждый итоговый файл придется загружать в файле "index.html" по отдельности через <script> или через загрузчик JavaScript-файлов.
            , publicPath: 'dist/' // Базовый путь.
            // При обычной сборке он подставляет этот путь в URL картинок и шрифтов в CSS-файлах.
            // При запуске через "webpack-dev-server" он указывает тому путь на папку "dist" с итоговыми файлами сборки, шрифтами и картинками относительно расположения файла index.html.
            // Влияет на переписывание путей до картинок в CSS-файлах. Лучше вместо его указания использовать "CopyWebpackPlugin" для копирования файла "index.html" в папку "dist".
            // , chunkFilename: '[name].bundle.js' // Используется для выделения файлов из изсходных файлов в файлы, которые согласно коду будут импортироваться динамически по ходу его выполнения.
            // Пример динамического импорта файла внутри исходника:
            // return import(/* webpackChunkName: "lodash" */ 'lodash').then(_ => {......}).catch(error => 'An error occurred while loading the component');
            // В результате в папке "dist" будет создан файл: lodash.bundle.js, который потом будет загружаться динамически.
            }

        , target: 'web' // Тип собираемого итогового файла.

        , resolve: {
              alias: { // Синонимы путей до файлов. Импорт модулей в исходных файлах можно делать по указанным синонимам, как модули из папки "node_modules". Это удобно, так как можно не указывать пути файлов относительно друг друга.
                  'inner-file': path.resolve(__dirname, 'src/inner/inner.js')
              }
          }

        , externals: { // Модули, которые надо из итогового файла сборки исключить. Они будут загружаться отдельно.
              'polyfills': 'polyfills'
            , 'lodash': '_' // Заменить импорт модуля на имя этой глобальной перемеменной: require('lodash') --> var _ В итоговый файл попадет: {1: function (...) {module.exports = _;}}
            , 'jquery': 'jQuery' // Заменить импорт модуля на имя этой глобальной перемеменной: require('jquery') --> var jQuery В итоговый файл попадет: {1: function (...) {module.exports = jQuery;}}
          }

        , module: {
            rules: [ // Набор используемых загрузчиков для различных типов файлов.
                  { // Загрузчик файлов, импортируемых в коде через import или require().
                      test: /\.css$/ // Регулярное выражение для поиска файлов данного типа.
                    , include: path.resolve(__dirname, 'src') // применять загрузчик только в файлам, находящимся в этой папке.
                    , use: ExtractWebpackTextPlugin.extract({ // Использование плагина для помещения всех загружаемых CSS-файлов в один общий итоговый выходной CSS-файл.
                              publicPath: '/dist' // Путь до картинок и шрифтов в CSS-файлах.
                            , fallback: 'style-loader' // Название используемого загрузчика.
                            , use: [ // Массив используемых загрузчиков. Загрузчики выполняются начиная с конца.
                                {
                                    loader: 'css-loader' // Название используемого загрузчика.
                                }
                            ]
                      })
                  }
                , { // Загрузчик файлов, импортируемых в коде через import или require().
                      test: /\.(png|jpg|gif)$/ // Регулярное выражение для поиска файлов данного типа.
                    , use: [ // Массив используемых загрузчиков. Загрузчики выполняются начиная с конца.
                          {
                              loader: 'url-loader' // Название используемого загрузчика.
                            , options: { // Опции загрузчика.
                                  limit: 1 // 8192
                              }
                          }
                    ]
                  }
            ]
          }

        , plugins: [ // Набор плагинов, которые обрабатывают итоговый файл после его сборки согласно порядку их следования в этом массиве. Порядок следования плагинов имеет значение.
              new CleanWebpackPlugin(['dist'])  // Плагин, удаляющий сборочную папку "dist".
            // , new webpack.optimize.UglifyJsPlugin() // Плагин, сжимающий итоговый файл сборки "bundle.js".
            , new webpack.optimize.CommonsChunkPlugin({ // Плагин, который находит общий для нескольких файлов код, например импорт библиотек, и помещает его в отдлеьный итоговый общий файл.
                  name: 'common' // Имя итогового файлы, в который будет помещен код, являющияйся общим для нескольких входных файлов.
              })
            , new ExtractWebpackTextPlugin('bundle.css') // Плагин, помещающий все входные файлы CSS в один общий итоговый выходной CSS-файл.
            , new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify('production')}) // Плагин для вставки различных переменных в итоговый файл сборки.
            , new webpack.NamedModulesPlugin() // Плагин для того, чтобы видеть для каких модулей произошла горячая замена HMR - Hot Module Replace.
            , new webpack.HotModuleReplacementPlugin() // Плагин для активации функции горячей замены модулей HMR - Hot Module Replace.
          ]

        , devServer: { // Настройки разработческого сервера. Адрес сервера по умолчанию: localhost:8080
              host: '127.0.0.1' // Хост, на котором будет запущен сервер.
            , port: 8080 // Порт, на котором будет запущен сервер.
            // , https: { // Настройки ключей для создания HTTPS сервера.
            //       key: fs.readFileSync('/path/to/server.key')
            //     , cert: fs.readFileSync('/path/to/server.crt')
            //     , ca: fs.readFileSync('/path/to/ca.pem')
            //   }
            , contentBase: '.' // Путь до папки, в которой находится файл index.html.
            // , publicPath: 'dist/' // Путь до папкм, в которой находится итоговый файл сборки.
            , hot: true // Включен режим горячей замены модулей HMR - Hot Module Replace.
                            // Пример кода горячего обновление модуля.
                            // import printMe from './print.js';
                            // printMe();
                            // if (module.hot) {
                            //     module.hot.accept('./print.js', function () { // Данный код будет выполнен при обновлении кода модуля print.js.
                            //         console.log('Accepting the updated printMe module!');
                            //         printMe();
                            //     });
                            // }
            , proxy: {
                  '/api': 'http://localhost:3000/api' // Проксирование запроса по этому адресу на другой сервер.
              }
            , headers: {
                  'X-Custom-Foo': 'bar' // Добавить данный заголовок ко всем ответам сервера.
              }
          }

        , devtool: 'inline-source-map' // Куда помещать source map.
        , bail: true // Не собирать итоговый файл, если во время сборки возникла хотя бы одна ошибка.
    }
];

Файл server.js

const express = require('express')
        , webpack = require('webpack')
        , webpackDevMiddleware = require('webpack-dev-middleware')
        , webpackConfig = require('./webpack.config.js');

const server = express();

server.use(webpackDevMiddleware(webpack(webpackConfig), {
    publicPath: webpackConfig[0].output.publicPath
}));

server.listen(3000, function () {
    console.log('Server is listening on 127.0.0.1:3000');
});

Файл package.json

{
      "name": "test"
    , "version": "1.0.0"
    , "dependencies": {
          "webpack": "2.7.0"
        , "webpack-dev-server": "2.11.1"
        , "webpack-dev-middleware": "2.0.5"
        , "css-loader": "0.28.9"
        , "style-loader": "0.20.1"
        , "file-loader": "1.1.6"
        , "url-loader": "0.6.2"
        , "clean-webpack-plugin": "0.1.18"
        , "extract-text-webpack-plugin": "2.1.2"
        , "express": "4.16.2"
        , "typescript": "2.7.1"
    }
}

Файл index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="dist/bundle.css">
    <title>Webpack App</title>
  </head>
  <body>
    <script src="dist/bundle.js"></script>
  </body>
</html>

Файл src/polyfills.js

console.log(1);

Файл src/vendors.js

console.log(2);

Файл src/index.js

import './index.css';

import a from './module.js';
import b from 'inner-file';

console.log(3);
console.log(a);
console.log(b);

var div = document.createElement('div');
div.id = 'my';
div.innerHTML = 'Привет.';
document.getElementsByTagName('body')[0].appendChild(div);

// Горячее обновление модуля.

import printMe from './print.js';

printMe();

if (module.hot) {
    module.hot.accept('./print.js', function () { // Данный код будет выполнен при обновлении кода модуля print.js.
        console.log('Accepting the updated printMe module!');
        printMe();
    });
}

Файл src/index.css

#my {
    width: 100px;
    height: 100px;
    background: url(image.png) no-repeat 0 0;
}

Файл src/print.js

export default function printMe() {
    console.log('I get called from print.js!');
    // console.log('Updating print.js...');
}

Файл src/module.js

var a = 4;

export default a;

Файл src/inner/inner.js

var b = 5;

export default b;

Комментариев нет:

Отправить комментарий