webpack4 создает строительные леса корпоративного уровня

Webpack

Передняя часть модульная

commjs использует синхронный способ загрузки модулей. Он экспортируется с помощью module.export и импортируется с помощью require. commjs подходит для использования на стороне сервера, поскольку серверная сторона быстрее считывает файлы с диска. Синхронная функция commjs позволяет использовать модули после компиляции. . Механизм загрузки commjs заключается в том, что значение require является копией значения module.export.И amd, и cmd используют механизмы асинхронной загрузки, которые в основном используются на стороне браузера.

    es6模块是ECMA 提出的javascript模块化的规范,将会成为一种通用解决方案。 commjs的加载方式是运行时加载, import是编译时加载, 编译时加载可以做指定输入,编译阶段做ast语法树解析可以进行摇树优化,还可以做静态优化的方案,而运行时加载则不能,因为tree-shaking的基础就是需要做静态分析的。

инструмент сборки проекта

На рынке их много, например, rollup, webpack, glup и Parcel.

    rollup专注于处理es mudule的处理,如果要实现其他模块的打包会比较繁琐和复杂,对一些splictChunk的方式支持的并不友好,不支持HMR, rollup更加精而美,如vue、react这些类库的源码都是通过rollup进行构建。相比较来说, rollup更适合类库的搭建,而webpack适合所有项目的构建。
    Parcel构建工具在一定意义上实现了零配置即可快速构建项目。配置过程依赖自动安装,而且自带多进程工作方式。但是还是更加推荐webpack,因为webpack是目前为止最好的构建工具, 在知名度,生态环境,插件市场,还有开发人员的熟知度。这每一点都无比的重要,而webpack是在每个点上都做到数一数二的水平,除了它的官方文档以外。

Роль инструментов сборки

Упаковать различные типы ресурсов, упаковать разрозненные js в коде в bundle.js, а синтаксис некоторых новых фич преобразовать в синтаксис, который может распознать носитель (браузер),

    代码转换,文件优化,代码分割, 模块合并, 自动刷新, 代码校验, 自动发布。 构建让开发流程更加自然,合理的构建让开发效率更加高效,提高效率和生产力, 目前的webpack还需要手动构建, 希望等到以后会出现一套集成的通用方案,接口暴露的更彻底,更友好。 就像以前的java开发使用ssm开发项目,需要进行一大堆的配置,配置过程痛苦而且繁琐,到了springboot的时代,就没有那么繁琐的配置了。前端构建工具的发展也会随着一系列的技术迭代而越来越友好。

Узнать о вебпаке

webpack4 предоставляет webpack-cli для запуска webpack, и в это время webpack также может выполнять нулевую настройку. Для некоторых необходимых конфигураций будут установлены значения по умолчанию. Например, запись по умолчанию имеет значение src/index.js, а вывод по умолчанию — build/main.js.

Файл конфигурации webpack изменяется через webpack.config.js, а файл конфигурации использует commonjs для экспорта данных конфигурации.

режим режим

В режиме режима веб-пакет для разработки и производства оптимизирует различные проекты в соответствии с различными режимами разработки, а персоналу по настройке необходимо выполнять разные процессы построения для разных сред.Среда разработки должна добавить некоторые вспомогательные инструменты разработки и некоторые решения по оптимизации для упаковки разработки. В производственной среде больше внимания уделяется уменьшению объема, а также разделению и публичному использованию модулей сжатия.

вход и выход

Вход и выход.Запись указывает, из какого файла начинать сборку.Bundle — это то, что веб-пакет упаковывает все разрозненные модули в коде в бандл, выходное местоположение бандла и другую выходную информацию. Выходная информация о местоположении должна быть абсолютным путем.

Упакованный модуль — это самовыполняющаяся функция, входящий параметр — объект, ключ — путь к упакованному файлу, значение — функция, функция eval используется для выполнения своей внутренней логики.

  • webpack идентифицирует moduleId для каждого модуля, поэтому, когда мы повторяем ссылку, мы не будем повторять упаковку, то есть еще раз выполним __webpack_require__(moduleId), чтобы получить кеш модуля в installModules

конфигурация контекста

конфигурации контекста, значением контекста является путь, путь является относительным путем входа и относительным путем html-webpack-plugin, то есть, когда мы настраиваем путь в контексте контекста, путь между входом и htmwebpack-plugin основан на этом пути,

разрешить конфигурацию

Конфигурацию разрешения можно использовать для настройки псевдонимов, которые можно использовать для сопоставления путей при импорте файла с помощью импорта в коде. Вы также можете сократить расширение импортируемого файла, например, import import ../index.js можно сократить как import ../index.

resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
        'vue$': 'vue/dist/vue.esm.js',
        '@': resolve('src'),
    }
},

Упаковка медиаресурсов

Чтобы упаковать некоторые медиа-ресурсы, используйте url-loader или file-loader, но url-loader имеет почти все функции file-loader, а также может быть настроен для преобразования base64 за пределы определенного размера, который находится в атрибуте имени url. -loader, Это позволяет нам настроить путь вывода файла, а также может классифицировать и управлять упакованными файлами. Значением name является путь к упакованному файлу и имя файла. Имя файла заменяется заполнителем [name], а тип файла заменяется заполнителем [ext]. Медиа-ресурсы здесь обычно относятся к

        // 注意这里打包图片的时候,要设置esModule: false,是版本问题,不然会报错。 
        png|jpe?g|gif|svg
        mp4|webm|ogg|mp3|wav|flac|aac
        // 注意如果你使用了elementui的话,这里是woff, 而不是woff2, 因为element-ui/lib/theme-chalk内是没有woff2文件的。
        woff|eot|ttf|otf
        

Например:

{
    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    loader: 'url-loader',
    exclude: [resolve('src/icons')],
    include: [resolve('src')],
    options: {
        esModule: false, // 版本问题
        limit: 8192,
        // 自定义目录和名称
        name: utils.assetsPath('img/[name].[hash:7].[ext]') // 打包后的文件会输出到指定目录的img/[name].[hash:7].[ext]
    }
},

Используйте svg-sprite-loader для упаковки svg

конфигурация devServer

В конфигурации в режиме разработки devServer является очень важным вспомогательным инструментом разработки, обеспечивающим HMR, сжатие gzip, работу с сервисом http, автоматическое открытие браузера, междоменный прокси, управление консольным выводом, ряд путей для статических ресурсов Служба запущена при использовании devServer не создает никаких файлов.DevServer хранит упакованные результаты в памяти и читает файлы в памяти, что значительно повышает эффективность. Внутри devServer также есть встроенный экспресс-сервер, ContentBase devServer размещает файлы, которые не упакованы webpack, но если вам также нужно получить доступ к каталогу статических ресурсов и использовать серверную маршрутизацию для точки, вам не нужно слишком много файловые операции ввода и вывода.

 devServer: {
    clientLogLevel: 'warning',
    historyApiFallback: {
        rewrites: [
            { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
        ],
    },
    hot: true,
    contentBase: false, // since we use CopyWebpackPlugin.
    compress: true,
    host: HOST || config.dev.host,
    port: PORT || config.dev.port,
    // open: config.dev.autoOpenBrowser,
    overlay: config.dev.errorOverlay
        ? { warnings: false, errors: true }
        : false,
    publicPath: config.dev.assetsPublicPath,
    proxy: config.dev.proxyTable,
    quiet: true, // necessary for FriendlyErrorsPlugin
    watchOptions: {
        poll: config.dev.poll,
    }
},

Файлы стиля пакета

Обработка загрузчиков в Webpack идет снизу вверх, при обработке .css файлов используются два загрузчика, css-loader и vue-style-loader (style-loader), здесь используется проект vue, и его нужно распарсить. Стиль стиля в файле vue должен обрабатываться vue-style-loader.

如果对于预处理样式文件的话,比如sass文件, 在加上sass-loader处理一遍再给css-loader....。  

О яме кэш-загрузчика

В более поздней оптимизации для оптимизации используется cache-loader. Использование cache-loader заключается в том, чтобы записать его перед загрузчиком, а затем выполнить анализ cache-loader. Если изменений нет, взять файл прямо из disk, что значительно повышает эффективность, но процесс парсинга и чтения файлов также требует времени, поэтому если загрузчик с большими потерями производительности выберет для обработки cache-loader, это значительно повысит эффективность упаковки. Однако, если вы столкнулись с mini-css-extract-plugin.loader, поставьте cache-loader перед mini-css-extract-plugin.loader, то вы вообще не будете паковать стили, идите к вопросам cache-loader. проблема

https://github.com/webpack-contrib/cache-loader/issues/40
你要将cache-loader写在mini-css-extract-plugin.loader的后面。
  • ps

Вставка слишком большого количества стилей приведет к блокировке страницы, поэтому используйте плагин mini-css-extract-plugin для извлечения стилей. Однако в среде разработки я не могу использовать mini-css-extract-plugin для выполнения горячего обновления css.Я нашел несколько решений в Интернете, но я могу использовать тег стиля для выполнения горячего обновления. Используйте плагин mini-css-extract-plugin в продакшене.

упаковать js-файлы

Webpack может обрабатывать только js и json по умолчанию, и обработка js является высшим приоритетом.Нам нужно преобразовать js в es2015, преобразовать синтаксис jsx и полифайл для статических методов некоторых классов.Для обработки синтаксиса генератора, js Подпакет и механизм ленивой загрузки — это все, что нужно делать js-файлам, и благодаря Babel они становятся проще. Например, некоторые песочницы, которые передают @babel/ployfile, не только велики, но и загрязняют глобальную среду песочницы, что не рекомендуется. Здесь core-js используется для полифайла метода класса

    {
      "presets": [
        [
          "@babel/preset-env",
          {
            "useBuiltIns": "usage", // or "usage"
            "corejs": 3
          }
        ]
      ],
      "plugins": [
        "transform-vue-jsx",
        "@babel/plugin-transform-runtime",
        "@babel/plugin-syntax-dynamic-import"
      ]
    }
因为js模块较多,就采用了多线程打包的方案,对js文件进行多线程打包,这里视情况而定,有些项目不一定需要多线程打包,因为分配线程需要消耗一定的资源,
如果电脑性能好,开的进程少,那么打包的速度就会提高,反之会降低。
happypack的使用很简单,匹配到js文件,使用happypack进行打包,指定id,该id会去找plugin中的HappyPack中的id,

对于js使用cache-loader,发现会很大程度上提高打包的速度,配合happypack大概提高8s左右的时间,
这里的时间不是固定的,是根据项目的大小和复杂程度来的,在一定程度上成正比。
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
new HappyPack({
    //用id来标识 happypack处理那里类文件
    id: 'js',
    //如何处理  用法和loader 的配置一样
    loaders: [
        {
            loader: 'cache-loader'
        },
        {
            loader: 'babel-loader?cacheDirectory=true',
        }
    ],
    //共享进程池
    threadPool: happyThreadPool,
    //允许 HappyPack 输出日志
    verbose: true,
}),
关于happypack对vue文件的多线程打包
vue-loader 15现在不支持happypack 因为happypack内部使用了虚拟的compiler和loaderContext,不建议使用happypack了,

Горячая замена матрицы

Никогда не используйте HMR в производстве, поэтому мы настраиваем его только в процессе разработки.

  • Так называемая горячая замена модуля означает горячее подключение модуля.При обновлении обновляется только измененный модуль, не мешая общему рабочему процессу программы и всем обновлениям.Мы знаем, что обновление означает потерю данных в памяти. для повторного приобретения ресурсов во многих сценариях очень важен HMR.
 // devserver中配置
 // 开启 HMR 特性,如果资源不支持 HMR 会 fallback 到 live reloading
 hot: true,
 // 表示不会回退到 使用刷新的方式进行重载
 // hotOnly: true
 
 // 配置hmr所需要的插件
 new webpack.HotModuleReplacementPlugin(),
  • Для общих css и img hmr работает из коробки, но для js hmr не может поддерживать общие схемы. Из-за неопределенности модуля экспорта js и неопределенности ссылки hmr не может выполнить для него общую схему обработки. Если вы хотите выполнить замену горячей пресс-формы на js, вам понадобится API, предоставленный HotModuleReplacementPlugin, чтобы вручную обработать модуль, для которого требуется hmr. Но, к счастью, мы используем фреймворк, и vue, и react интегрируют решение hmr, они заставят эти js-модули обрабатываться единообразно и добавят метод moudle.hot для оценки. Нам просто нужно это из коробки. Используемый внутри vue-loade vue-hot-reload-api во vue будет интегрирован в схему hot-reload.Если используется нативный js, то нужно вручную заменить js на hot-mo, а фреймворк сделал набор интеграции Он также предусматривает метод экспорта и структуру данных модуля, поэтому фреймворк так удобен для интеграции набора общих схем замены горячего модуля.

Поддержка плагинов

// 重载之后在控制台显示的file name 是更新的文件的名字,默认的是文件的id
new webpack.NamedModulesPlugin(), 

sourcemap

  • Режим исходной карты в webpack нужно включать с помощью devtool, который подробно описан на официальном сайте здесь.

     补充几个小点:eval模式放在一个临时的虚拟机中运行,VM154:1 // 
     
    

  • Каждый фрагмент кода объявляется через sourceURL

  • eval, скорость построения очень высокая, вы можете получить строку и столбец ошибки в исходном коде, но вы не можете просмотреть информацию о конкретной строке и столбце, потому что он не может просматривать исходный код, только преобразованный код.
  • В режиме исходной карты будет создан файл .map, и упакованный файл можно сопоставить с исходным файлом через файл .map.
  • eval-source-map может находить файлы и информацию о конкретных строках и столбцах (поскольку могут быть сгенерированы файлы сопоставления исходной карты),
  • Cheap-eval-source-map может находить файлы, но не может находить определенные столбцы, только определенные строки, и это код, преобразованный загрузчиком, но скорость сборки улучшена.
  • Cheap-module-eval-source-map аналогичен дешевой-eval-source-map, но представляет собой исходный код до преобразования загрузчика.

В среде разработки devtool, как правило, является наиболее подходящим выбором для проекта.Это дешевая-модульная-eval-source-map.Его упаковка и скорость построения хорошие, и он может создавать исходный код, который можно отлаживать. В среде используется false, а сборка и упаковка Fastest не генерируют исходный код и другие дополнительные файлы. Если есть ошибка в производственной среде, но такой ошибки нет в других средах, если вы хотите найти и не хотите раскрывать исходный код, вы можете использовать nosources-source-map

Оптимизация среды разработки

dll: В проекте мы обычно используем некоторые сторонние пакеты, и эти сторонние пакеты имеют фиксированную версию и не будут обновляться итеративно, и нам нужно упаковывать эти сторонние пакеты каждый раз, когда мы упаковываем, что пустая трата времени, поэтому разработка В среде мы используем библиотеку ссылок dll, чтобы сначала упаковать некоторые фиксированные файлы, а затем использовать манифест для их импорта.Сначала мы создаем новый файл конфигурации dll_webpack (настройка режима разработки), а затем используйте подключаемый модуль DllReferencePlugin, который поставляется с веб-пакетом, в файле конфигурации веб-пакета, необходимом для среды разработки.Плагин связывает уже упакованные сторонние ресурсы.

Нам нужно вручную импортировать упакованный файл dll.js в index.html.Мы можем динамически импортировать упакованный файл js в index.html через плагин AddAssetHtmlPlugin.

// webpack.dll.config.js
const webpack = require('webpack')
const utils = require('./utils')
const config = require('../config')
const path = require('path')

module.exports = {
  mode: 'development',
  entry: {
    hk: ['vue/dist/vue.esm.js', 'vuex', 'echarts', 'vue-router', 'element-ui']
  },
  output: {
    filename: '_dll_[name].js',
    // path: path.resolve(__dirname, 'dll'),
    path: path.resolve(__dirname, 'dll'),
    library: '_dll_[name]',
    // libraryTarget: 'var'
  },
  plugins: [
    new webpack.DllPlugin({
      name: '_dll_[name]',
      // path: path.resolve(__dirname, 'dll', 'manifest.json')
      path: path.resolve(__dirname, 'dll', 'manifest.json'),
    })
  ]
}
// webpack.config.js
// 将dll链接库的内容放到html中
new AddAssetHtmlPlugin({ filepath: require.resolve('./dll/_dll_hk.js') }),
new webpack.DllReferencePlugin({
    manifest: path.resolve(__dirname, 'dll', 'manifest.json')
}),

Оптимизация производственной среды

Сжать код при использовании плагина mini-css-extract-plugin

 当使用mini-css-extract-plugin进行提取css文件时, css文件不会被打包, 我们可以使用在minimizer中使用optimize-css-assets-webpack-plugin 进行压缩css代码,但是当使用minimizer属性的时候,webpack就会认为你不再使用默认的压缩方式了,而是使用自定义的压缩方式。所以还要手动的添加webpack内置的压缩js的插件terser-webpack-plugin
optimization: {
    minimize: true, // production模式会自动开启摇树优化  usedExports  和  minimize  和  sideEffects 
    splitChunks: {
        chunks: "all",
        minSize: 16000, // 模块的最小体积
        minChunks: 1, // 模块的最小被引用次数
        maxAsyncRequests: 5, // 按需加载的最大并行请求数
        maxInitialRequests: 3, // 一个入口最大并行请求数
        automaticNameDelimiter: '~', // 文件名的连接符
        name: true,
        cacheGroups: { // 缓存组
            vendors: {  //第三方
                test: /[\\/]node_modules[\\/]/,
                priority: -10//权重
            },
            default: {
                minChunks: 2,
                priority: -20,
                reuseExistingChunk: true
            }
        }
    },
    minimizer: [
        new TerserJSPlugin({
            cache: true, // 是否缓存
            parallel: true, // 是否并行打包
            sourceMap: false // 是否开始源码映射
        }),
        new OptimizeCSSPlugin({})
    ],
},
  1. tree-shaking Оптимизация встряхивания дерева Встряхивание дерева заключается в том, чтобы встряхнуть желтые листья на дереве, чтобы они упали, образуя новое дерево. И webpack удалит этот неиспользуемый код с помощью оптимизации встряхивания дерева. Tree-shaking с опцией оптимизации при минимизации автоматически сжимает неиспользуемый код. Для веб-пакета не весь код модуля может встряхивать дерево.Обычным является loadsh.Если вы вводите loadsh и используете только один из этих методов, веб-пакет по-прежнему будет упаковывать все остальные методы loadsh, встряхивание дерева недопустимо, потому что по умолчанию метод экспорта loadsh — это commonjs, а предпосылка встряхивания дерева заключается в том, что модуль — это esModule.
  2. сфера подъема Если нет подъема области видимости, то в самовыполняющейся функции после упаковки будут какие-то переменные, роль которых — повлиять на другой результат после серии вычислений. И эти вещи будут потреблять память для хранения при работе на стороне браузера, а также могут генерировать большое количество замыканий (необходимо указать область действия функции), что приводит к потреблению памяти, а подъем области может поместить эту статику в область видимости и объединить их. Уменьшенный размер пакета и накладные расходы памяти.
  3. сплитчанки Чтобы разбить код на части, splitchunk упакует модули ресурсов в нашем проекте в разные пакеты в соответствии с правилами дизайна. Основное использование в проекте — это сочетание с функцией динамического импорта ESModules для загрузки модулей по запросу. И может извлечь общую часть кода. Извлечение сторонних поставщиков и бизнес-кода