"предисловие"
Эта серия является предыдущим постом автораОкончание фронтенда высокочастотного интервьюДополнение будет больше тяготеть к вопросам мидл и хай-энд фронтенд интервью.Конечно, все прошли путь от новичка, и заинтересованные друзья могут его посмотреть.
"Подать жалобу:"Упоминание вебпака действительно грустное и слезливое.Помню, когда только вышла версия 1.0 вебоака, я следил за документацией и просматривал пункты конфигурации и ту же конфигурацию, что и на официальном сайте, но я не мог понять всевозможные ошибки. время, это был действительно веб-пакет, когда я только что сделал внешний интерфейс.От входа до отказа, особенно сейчас, когда вы проходите собеседование на старшие позиции переднего плана, вы обнаружите, что интервьюеры любят спрашивать о вещах, связанных с веб-пакетом.Я видел несколько крупных фабрик берут интервью у самих себя и начинают использовать webpack после своих интервью, ха-ха(Может быть, это потому, что у меня есть некоторый опыт архитектуры в моем резюме)
"Изменять:"На данный момент webpack дошел до версии 4.0.Оптимизированы официальные документы и многое другое.Теперь он проще в использовании и различные скаффолдинги в принципе помогают нам настроить webpack,но это не значит что нам не нужно знать принцип работы webpack потому что мы стоим с точки зрения архитектуры интерфейса.Необходимо уметь анализировать пакет автоматизации интерфейса.В то же время, как промежуточный и продвинутый интерфейс, также необходимо твердо усвоить фронтальные инструменты.
1 Что такое вебпак
Webpack — это автоматизированное решение для упаковки, которое также можно понимать как сборщик модулей. Это помогает нам анализировать структуру проекта, находить модули JavaScript и другие языки расширения (Scss, TypeScript и т. д.), которые браузеры не могут запускать напрямую, и упаковывать их в подходящие форматы для использования браузерами.
Если нет веб-пакета, сколько нам придется вручную обрабатывать вышеперечисленные вещи
2 Каковы общие конфигурации веб-пакета
- Entry: Entry, первый шаг в выполнении сборки Webpack начнется с Entry, который можно абстрагировать во входные данные.
- Вывод: выведите результат после того, как Webpack пройдет серию обработок и получит окончательный желаемый код.
- режим: предоставляет параметр конфигурации режима, который указывает веб-пакету использовать встроенные оптимизации для соответствующего режима.
- Модуль: модуль, все является модулем в Webpack, а модуль соответствует файлу.
- Чанк: блок кода, фрагмент состоит из нескольких модулей для слияния и разделения кода.
- Загрузчик: преобразователь модулей, который используется для преобразования исходного содержимого модуля в новое содержимое по мере необходимости.
- Плагин: плагин расширения, который внедряет логику расширения в определенное время в процессе сборки Webpack, чтобы изменить результат сборки или сделать то, что вы хотите.
3 рабочий процесс веб-пакета
- Разбор параметров: чтение и объединение параметров из файлов конфигурации и операторов оболочки для получения окончательных параметров.
- Найдите файл записи: начните с модуля, настроенного в записи, для рекурсивного разрешения всех модулей, от которых зависит запись.
- Вызовите загрузчик для компиляции файла: каждый раз, когда модуль будет найден, соответствующее правило преобразования будет найдено в соответствии с настроенным загрузчиком.
- Пройдите AST и соберите зависимости: после преобразования модуля проанализируйте модуль, от которого зависит текущий модуль.
- Генерация фрагмента: эти модули будут сгруппированы в единицы Записи, Запись и все ее зависимые Модули разделены на группу, которая является Чанком.
- Выходной файл: наконец, Webpack преобразует все фрагменты в выходной файл.
Студенты, которые хотят увидеть исходный код конкретного принципа компиляции веб-пакетапортал
4 Общая конфигурация загрузчика и рабочий процесс
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{ test: /\.js$/, use: 'babel-loader' },
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'postcss-loader' },
]
}
]
}
};
"Рабочий процесс загрузчика"
- Загрузчик модуля настраивается в webpack.config.js;
- Когда встречается соответствующий файл модуля, запускается загрузчик модуля;
- Загрузчик принимает источник, представляющий содержимое файла модуля;
- Загрузчик использует ряд API-интерфейсов, предоставляемых webapck, для преобразования исходного кода и получения результата;
- Возвращайте или передайте результат следующему загрузчику, пока обработка не будет завершена.
Взгляните на пример less-loader (о конкретной реализации загрузчика см.Пример официального сайта)
let less = require('less');
module.exports = function (source) {
const callback = this.async();
//this.async() 返回一个回调函数,用于异步执行
less.render(source, (err, result) => {
//使用less处理对应的less文件的source
callback(err, result.css);
});
}
5 распространенных конфигураций плагинов и простые принципы
"Знакомство с общими плагинами проекта"
- extract-text-webpack-plugin
По умолчанию webpack упаковывает css как модуль в чанк.
const ExtractTextPlugin = require('extract-text-webpack-plugin');
new ExtractTextPlugin({
filename: 'css/[name].css',
})
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: ['css-loader','postcss-loader','less-loader'],
fallback: 'vue-style-loader', #使用vue时要用这个配置
})
},
- html-webpack-плагин Этот плагин очень важен.Первой функцией является создание файлов HTML-страницы в вашем выходном каталоге, а второй функцией является автоматическое добавление фрагментов, упакованных webpack, в этот HTML.
const HtmlPlugin = require('html-webpack-plugin')
new HtmlPlugin({
filename: 'index.html',
template: 'pages/index.html'
}
- определить плагин определить глобальные константы
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
},
PRODUCTION: JSON.stringify(PRODUCTION),
APP_CONFIG: JSON.stringify(appConfig[process.env.NODE_ENV]),
}),
- UglifyJsПлагин сжатие js
new webpack.optimize.UglifyJsPlugin()
❝Примечание: webpack4 удалил этот плагин, используйте вместо него оптимизацию.минимизировать
❞
- CommonsChunkПлагин CommonsChunkPlugin в основном используется для извлечения сторонних библиотек (таких как jQuery) и общедоступных модулей (обычных js и css), которые часто используются в многостраничных приложениях для создания общедоступных фрагментов и предотвращения повторных ссылок.
{
entry: {
vendor: 'index.js'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: ['vendor','runtime'],
filename: '[name].js'
}),
]
}
❝Примечание: webpack4 удалил этот плагин, используйте вместо него оптимизацию.SplitChunks.
❞
"Простой принцип"
Плагин похож на функцию, встроенную в производственную линию, обрабатывающую ресурсы на производственной линии в определенное время. Webpack использует Tapable для организации этой сложной производственной линии. В процессе компиляции кода вебпак вызовет серию событий Tapable hook, что делает плагин, так это находит соответствующий хук и вешает на него свою задачу, то есть событие регистрации.Таким образом, когда вебпак построен, подключаемый модуль регистрируется. Событие будет выполнено при срабатывании хука.
Плагин webpack состоит из следующего:
- Именованная функция JavaScript.
- Определите метод применения в прототипе функции плагина.
- Указывает обработчик событий, привязанный к самому веб-пакету.
- Обрабатывать внутренние данные конкретного экземпляра веб-пакета.
- Вызовите обратный вызов, предоставленный веб-пакетом, после завершения функции.
"Пример пользовательского плагина"(Для получения дополнительной информации, пожалуйста, посетите официальный сайтСоздать плагин)
// 一个 JavaScript 命名函数。 function MyExampleWebpackPlugin() {};
// 在插件函数的 prototype 上定义一个
applyметод. MyExampleWebpackPlugin.prototype.apply = функция (компилятор) { // Указываем обработчик событий для подключения к самому веб-пакету. компилятор.plugin('webpacksEventHook', function(compilation /* Обработка данных, специфичных для внутреннего экземпляра webpack. */, callback) { console.log("Это пример плагина!!!");// 功能完成后调用 webpack 提供的回调。 callback();}); };
скопировать код
6 Что делать, если скорость упаковки webpack слишком низкая
- Уменьшите объем компиляции и сократите ненужную работу по компиляции, то есть используются модули, mainFields, noParse, include, exclude, alias.
const resolve = dir => path.join(__dirname, '..', dir);
resolve: {
modules: [ // 指定以下目录寻找第三方模块,避免webpack往父级目录递归搜索
resolve('src'),
resolve('node_modules'),
resolve(config.common.layoutPath)
],
mainFields: ['main'], // 只采用main字段作为入口文件描述字段,减少搜索步骤
alias: {
vue$: "vue/dist/vue.common",
"@": resolve("src") // 缓存src目录为@符号,避免重复寻址
}
},
module: {
noParse: /jquery|lodash/, // 忽略未采用模块化的文件,因此jquery或lodash将不会被下面的loaders解析
// noParse: function(content) {
// return /jquery|lodash/.test(content)
// },
rules: [
{
test: /\.js$/,
include: [ // 表示只解析以下目录,减少loader处理范围
resolve("src"),
resolve(config.common.layoutPath)
],
exclude: file => /test/.test(file), // 排除test目录文件
loader: "happypack/loader?id=happy-babel" // 后面会介绍
},
]
}
- Плагин webpack-parallel-uglify-plugin (оптимизирует процесс сжатия js)
webpack-parallel-uglify-plugin может разбивать задачи на несколько подпроцессов для одновременного выполнения.После обработки подпроцессов результаты отправляются в основной процесс, чтобы добиться параллельной компиляции и значительно повысить скорость сжатия js.
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
// ... optimization: { minimizer: [ new ParallelUglifyPlugin({ // 多进程压缩 cacheDir: '.cache/', uglifyJS: { output: { comments: false, beautify: false }, compress: { warnings: false, drop_console: true, collapse_vars: true, reduce_vars: true } } }), ] }
- HappyPack
Когда веб-пакет запущен и упакован в узле, это один поток, который выполняет одно действие одно за другим. HappyPack может открывать несколько подпроцессов для одновременного выполнения. После обработки подпроцессов результаты передаются основному процессу. .
const HappyPack = require('happypack');
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, './dist'),
filename: 'main.js',
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: 'happypack/loader?id=babel',
},
]
},
plugins: [
new HappyPack({
id: 'babel', //id值,与loader配置项对应
threads: 4, //配置多少个子进程
loaders: ['babel-loader'] //用什么loader处理
}),
]
}
- динамическое связывание DLL
Сторонняя библиотека не обновляется часто, и есть надежда, что она будет упакована отдельно при упаковке для повышения скорости упаковки. Для упаковки dll необходимо создать новый файл конфигурации вебпака (webpack.dll.config.js) При упаковке dll вебпак делает индекс и записывает его в файл манифеста. Затем вам нужно только прочитать файл манифеста при упаковке файла проекта.
const webpack = require("webpack"); const path = require('path'); const CleanWebpackPlugin = require("clean-webpack-plugin"); const dllPath = path.resolve(__dirname, "../src/assets/dll"); // dll文件存放的目录
module.exports = { entry: { // 把 vue 相关模块的放到一个单独的动态链接库 vue: ["babel-polyfill", "fastclick", "vue", "vue-router", "vuex", "axios", "element-ui"] }, output: { filename: "[name]-[hash].dll.js", // 生成vue.dll.js path: dllPath, library: "dll[name]" }, plugins: [ new CleanWebpackPlugin(["*.js"], { // 清除之前的dll文件 root: dllPath, }), new webpack.DllPlugin({ name: "dll[name]", // manifest.json 描述动态链接库包含了哪些内容 path: path.join(__dirname, "./", "[name].dll.manifest.json") }), ], };
Далее вам нужно добавить команду dll в package.json.
"scripts": {
"dll": "webpack --mode production --config build/webpack.dll.config.js"
}
После запуска npm run dll будут сгенерированы файлы описания ресурсов ./src/assets/dll/vue.dll-[hash].js public js и ./build/vue.dll.manifest.json. dll работа по подготовке завершена, на нее можно ссылаться в webpack.
externals: {
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex': 'vuex',
'elemenct-ui': 'ELEMENT',
'axios': 'axios',
'fastclick': 'FastClick'
},
plugins: [
...(config.common.needDll ? [
new webpack.DllReferencePlugin({
manifest: require("./vue.dll.manifest.json")
})
] : [])
]
7 Как webpack оптимизирует производительность интерфейса
- Загрузка сторонних библиотек по запросу, ленивая загрузка маршрутов
//第三方ui库element,vant等库都提供来按需加载的方式,避免全部引入,加大项目体积 import { Button, Select } from 'element-ui';
//路由懒加载 const showImage = () => import('@/components/common/showImage');
- разделение кода
- Извлечь сторонние библиотеки"vendor"
module.exports = {
entry: {
main: './src/index.js',
vendor: ['react', 'react-dom'],
},
}
- Разделение библиотеки зависимостей"splitChunks"
optimization: {
splitChunks: {
chunks: "async", // 必须三选一: "initial" | "all"(推荐) | "async" (默认就是async)
minSize: 30000, // 最小尺寸,30000
minChunks: 1, // 最小 chunk ,默认1
maxAsyncRequests: 5, // 最大异步请求数, 默认5
maxInitialRequests : 3, // 最大初始化请求书,默认3
automaticNameDelimiter: '~',// 打包分隔符
name: function(){}, // 打包后的名称,此选项可接收 function
cacheGroups:{ // 这里开始设置缓存的 chunks
priority: 0, // 缓存组优先级
vendor: { // key 为entry中定义的 入口名称
chunks: "initial", // 必须三选一: "initial" | "all" | "async"(默认就是async)
test: /react|lodash/, // 正则规则验证,如果符合就提取 chunk
name: "vendor", // 要缓存的 分隔出来的 chunk 名称
minSize: 30000,
minChunks: 1,
enforce: true,
maxAsyncRequests: 5, // 最大异步请求数, 默认1
maxInitialRequests : 3, // 最大初始化请求书,默认1
reuseExistingChunk: true // 可设置是否重用该chunk
}
}
}
},
- Удалить лишний код
"Tree-Shaking"
Группа передовых рыболовных технологий Brother Shark
Приветствую всех на технических биржахСвязь