1 Сузить поиск файлов
1 include & exclude
1) action
- Ограничить область компиляции
2) useage
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader?cacheDirectory'],
include: path.resolve(__dirname, 'src'),
exclude: /node_modules/
}
]
}
'babel-loader?cacheDirectory'
You can also speed up babel-loader by as much as 2x by using the cacheDirectory option. This will cache transformations to the filesystem.
QA
предупреждение командной строки
[BABEL] Note: The code generator has deoptimised the styling of "/Users/xxx/Documents/xxx/webpack_test/test3/node_modules/lodash/lodash.js" as it exceeds the max of "500KB".
Добавление диапазона ограничения исключения не приведет к сообщению об ошибке
2 resolve.modules
1) action
- Tell webpack what directories should be searched when resolving modules.
2) useage
resolve: {
modules: [path.resolve('node_modules'), path.resolve('lib')]
}
3) note
-
Absolute and relative paths can both be used, but be aware that they will behave a bit differently.
-
A relative path will be scanned similarly to how Node scans for node_modules, by looking through the current directory as well as it's ancestors (i.e. ./node_modules, ../node_modules, and on).
-
With an absolute path, it will only search in the given directory.
-
Если вы хотите добавить каталог для поиска, который имеет приоритет над node_modules/: (то есть по порядку)
modules: [path.resolve(__dirname, "src"), "node_modules"]
4) QA
Module not found: Error: Can't resolve 'ajax' in '/Users/xxx/Documents/xxx/webpack_test/test3/src'
Когда вам нужно указать другие каталоги модулей, кроме node_modules, вы можете добавить атрибуты в массив
3 resolve.mainFields
1) action
- Resolve.mainFields в конфигурации Webpack используется для настройки того, какой файл записи используется сторонними модулями.
В установленном стороннем модуле будет файл package.json, который используется для описания свойств этого модуля, часть из которых используется для описания того, где находится файл входа, а для настройки какого поля используется разрешение.mainFields используется как описание входного файла.
Причина, по которой может быть несколько полей, описывающих входной файл, заключается в том, что некоторые модули могут использоваться в нескольких средах одновременно, и для разных сред выполнения необходимо использовать разный код. Возьмем в качестве примера API-интерфейс isomorphic-fetch, который является реализацией Promise, но может использоваться как в браузере, так и в среде Node.js.
2) useage
Для того, чтобы сократить шаги поиска, при указании поля описания файла входа стороннего модуля можно задать его как можно меньше. Поскольку большинство сторонних модулей используют основное поле для описания местоположения файла записи, вы можете настроить Webpack следующим образом:
module.exports = {
resolve: {
// 只采用 main 字段作为入口文件描述字段,以减少搜索步骤
mainFields: ['main'],
},
};
4 resolve.alias
1) action
- Элемент конфигурации сопоставляет исходный путь импорта с новым путем импорта через псевдоним.
- Этот метод оптимизации влияет на использование Tree-Shaking для удаления мертвого кода.
2) useage
alias: {
"bootstrap": "bootstrap/dist/css/bootstrap.css"
}
5 resolve.extensions
1) action
- Когда оператор импорта не имеет суффикса файла, Webpack автоматически добавит суффикс, чтобы попытаться спросить, существует ли файл -
- Суффикс по умолчанию — расширения: ['.js', '.json']
2) useage
3) note
- Старайтесь, чтобы список суффиксов был как можно меньше.
- Самая высокая частота идет вперед
- Максимально используйте суффиксы в операторах экспорта
6 module.noParse
1) action
- Элемент конфигурации module.noParse позволяет Webpack игнорировать рекурсивный анализ некоторых файлов, которые не являются модульными.
2) useage
module: {
noParse: [/react\.min\.js/]
}
2) note
Игнорируемые файлы не должны содержать import , require , define и другие модульные операторы.
Две DLL
1 action
Файл с dll в качестве суффикса называется динамической библиотекой, Динамическая библиотека может содержать функции и данные, вызываемые другими модулями.
- Разделите базовые модули на отдельные динамически подключаемые библиотеки.
- Когда импортируемый модуль находится в динамической библиотеке, модуль не может быть снова упакован, но получен из динамической библиотеки.
2 usage
Определить подключаемый модуль (DLLPlugin) ---> Ссылочный подключаемый модуль (DllReferencePlugin)
В этом примере используется jquery в качестве примера
1) Определите DLL
- Используется для упаковки библиотеки динамической компоновки.
- нужно строить отдельно
webpack.jquery.config.js
module.exports = {
entry: ["jquery"],
output: {
filename: "vendor.js",
path: path.resolve(__dirname, "dist"),
libraryTarget: 'var',// 打包的方式,hou
library: "vendor_lib_vendor"// DLL的名字
},
plugins: [
new webpack.DllPlugin({
name: "vendor_lib_vendor",// 定义DLL
path: path.resolve(__dirname, "dist/vendor-manifest.json")
})
]
};
Добавьте скрипты в package.json
"dll": "webpack --config webpack.jquery.config.js --mode development"
После настройки вышеуказанных файлов запустите в терминалеnpm run dll
, в каталоге dist будут сгенерированы два файла,vendor.js
а такжеvendor-manifest.json
.vendor.js
В комплекте есть упакованныйjquery
код файла,vendor-manifest.json
используется для ассоциации. DLL определена, и следующим шагом является применение упакованной DLL.
2) Справочная DLL
Библиотека динамической компоновки, упакованная плагином DllPlugin, внесена в конфигурационный файл webpack.config.js.
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require("./dist/vendor-manifest.json")
})
],
3) Использование DLL
app.html Добавить внизу app.html
<script src="./vendor.js"></script>
3 note
libraryTarget
а такжеlibrary
Они необходимы при использовании Webpack для создания библиотеки, которую можно импортировать и использовать другими модулями.
- output.libraryTarget настраивает способ экспорта библиотеки.
- output.library настраивает имя библиотеки экспорта. Обычно они используются вместе.
output.libraryTarget — это тип перечисления строк, который поддерживает следующие конфигурации.
1) переменная (по умолчанию)
Написанная библиотека будет назначена через var переменной с именем via library.
Если output.library='LibraryName' настроен, выходные и используемые коды следующие:
// Webpack 输出的代码
var LibraryName = lib_code; //其中 lib_code 代指导出库的代码内容,是有返回值的一个自执行函数。
// 使用库的方法
LibraryName.doSomething();
2) commonjs
Написанные библиотеки будут экспортированы через спецификацию CommonJS.
Если output.library='LibraryName' настроен, выходные и используемые коды следующие:
// Webpack 输出的代码
exports['LibraryName'] = lib_code;
// 使用库的方法
require('library-name-in-npm')['LibraryName'].doSomething();
// 其中 library-name-in-npm 是指模块发布到 Npm 代码仓库时的名称。
3) commonjs2
Написанная библиотека будет экспортирована через спецификацию CommonJS2, а код вывода и использования будет следующим:
// Webpack 输出的代码
module.exports = lib_code;
// 使用库的方法
require('library-name-in-npm').doSomething();
Спецификации CommonJS2 и CommonJS очень похожи, разница в том, что CommonJS можно экспортировать только экспортами, а CommonJS2 добавляет метод экспорта module.exports на основе CommonJS. Когда output.libraryTarget имеет значение commonjs2, настройка output.library не имеет смысла.
4) this
Написанной библиотеке будет присвоено имя, указанное библиотекой через this , а код вывода и использования будет следующим:
// Webpack 输出的代码
this['LibraryName'] = lib_code;
// 使用库的方法
this.LibraryName.doSomething();
5) window
Написанной библиотеке будет присвоено имя, указанное библиотекой через окно, то есть библиотека будет смонтирована в окне, а вывод и используемые коды будут следующими:
// Webpack 输出的代码
window['LibraryName'] = lib_code;
// 使用库的方法
window.LibraryName.doSomething();
6) global
Написанной библиотеке будет присвоено имя, указанное библиотекой через глобальную, то есть библиотека будет смонтирована на глобальную, а вывод и используемые коды будут следующими:
// Webpack 输出的代码
global['LibraryName'] = lib_code;
// 使用库的方法
global.LibraryName.doSomething();
Три счастливых пакета
1 action
HappyPack позволяет Webpack разбивать задачи на несколько подпроцессов для одновременного выполнения, а затем отправлять результаты в основной процесс после обработки подпроцессов.
2 usage
install
Поскольку webpack 4.0 только что вышел, плагин ответа еще не обновлялся, но вы можете добавить его позже.@next
для установки следующей версии
npm i happypack@next -D
webpack.config.js
module: {
rules: [
{
test: /\.css$/,
use: 'happypack/loader?id=css',
//把对.js文件的处理转交给id为babel的HappyPack实例
//用唯一的标识符id来代表当前的HappyPack是用来处理一类特定文件
include: path.resolve('./src'),
exclude: /node_modules/
},
{
test: /\.js/,
use: 'happypack/loader?id=babel',
include: path.resolve('./src'),
exclude: /node_modules/
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './src/index.html'
}),
new HappyPack({
id: 'babel',
loaders: ['babel-loader']// 和rules里的配置相同
}),
new HappyPack({
id: 'css',
loaders: ['style-loader', 'css-loader']// 和rules里的配置相同
}),
]
Плагин Four ParallelUglify
1.action
- Вы можете превратить последовательное сжатие файлов JS в открытие нескольких подпроцессов для параллельного выполнения.
2 usage
insatll
npm install webpack-parallel-uglify-plugin -D
webpackage.config.js
new ParallelUglifyPlugin({
workerCount: os.cpus().length - 1,//开启几个子进程去并发的执行压缩。默认是当前运行电脑的 CPU 核数减去1
uglifyJS: {
output: {
beautify: false, //不需要格式化
comments: true, //不保留注释
},
compress: {
warnings: false, // 在UglifyJs删除没有用到的代码时不输出警告
drop_console: true, // 删除所有的 `console` 语句,可以兼容ie浏览器
collapse_vars: true, // 内嵌定义了但是只用到一次的变量
reduce_vars: true, // 提取出出现多次但是没有定义成变量去引用的静态值
}
}
})
Автоматическое обновление пяти серверов
1 файловый монитор
1) action
- Вы можете отслеживать изменения файлов и перекомпилировать их при изменении файла.
2) useage
watch: true,
watchOptions: {
ignored: /node_modules/,
aggregateTimeout: 300,
poll: 1
}
3) note
watch
watchOptions имеет смысл только при включенном режиме прослушивания (watch true)
aggregateTimeout
После отслеживания изменения подождите 300 (мс) перед выполнением действия, чтобы предотвратить слишком быстрое обновление файла и слишком высокую частоту компиляции.
poll
Определите, изменился ли файл, постоянно спрашивая, изменился ли файл, по умолчанию 1000 раз в секунду.
процесс мониторинга файлов
Webpack регулярно получает время обновления файла и сравнивает его с последним сохраненным временем.Несоответствие означает, что было изменение, и опрос используется для настройки того, сколько раз в секунду.
Когда обнаруженный файл больше не изменяется, он будет сначала кэширован, а слушатель будет уведомлен после ожидания в течение определенного периода времени.Это время ожидания настраивается агрегатом.
webpack будет прослушивать только те файлы, от которых зависит запись Нам нужно минимизировать количество файлов, которые необходимо контролировать, и частоту проверки, естественно, уменьшение частоты приведет к снижению чувствительности.
2 Автоматически обновлять браузер
1) use
devServer: {
inline: true
},
2) note
webpack отвечает за мониторинг изменений файлов, а webpack-dev-server отвечает за обновление браузера. Эти файлы будут упакованы в куски, которые будут проксировать клиента, чтобы инициировать соединение WebSocket с сервером.
3 модуля горячей замены
1) action
- Технология горячей замены модуля позволяет обновить только указанный модуль, не обновляя всю веб-страницу.
- Принцип заключается в том, что при изменении исходного кода перекомпилируется только измененный модуль, а соответствующий старый модуль в браузере заменяется новым выходным модулем.
2) Преимущества
- Более быстрый отклик и меньшее время
- Рабочее состояние веб-страницы можно сохранить без обновления веб-страницы.
- Слушайте меньше файлов
- Игнорировать файлы в каталоге node_modules
2) use
webpack.config.js
devServer: {
hot:true//将hot设置为true
},
// 需要的插件
plugins: [
new webpack.NamedModulesPlugin(),//显示模块的相对路径
new webpack.HotModuleReplacementPlugin()// 启动热加载功能
]
code
if (module.hot) {
module.hot.accept('./hot.js', () => {
let hot = require('./hot');
document.getElementById('app2').innerHTML = hot + '1';
})
}
3 note
Модули, требующие горячей загрузки, необходимо вводить в модуль во время инициализации, иначе HMR не сработает.
Шесть различают окружающую среду
1 action
При разработке веб-страницы обычно используется несколько наборов работающих сред, например среда, облегчающая разработку и отладку в процессе разработки. Среда выполнения, опубликованная в Интернете для использования пользователями.
Основные отличия онлайн-среды от среды разработки заключаются в следующем:
- Код в строке сжат
- Среда разработки может печатать журналы, которые могут видеть только разработчики.
- Внутренний интерфейс данных среды разработки и онлайн-среды может отличаться
2 usage
package.json
-
cross-env
Установите кросс-платформенные переменные среды (без && после него)
"scripts": {
"build-dev": "cross-env NODE_ENV=development webpack --mode development",
"build-prod": "cross-env NODE_ENV=production webpack --mode production"
}
webpack.config.js
- Различать производственную среду и среду разработки в соответствии с переменными среды, а затем и
webpack.base.config.js
Слияние, производственная среда (или среда разработки) имеет более высокий приоритетwebpack.base.config.js
Конфигурация.
let merge = require('webpack-merge');
let base = require('./webpack.base.config');
let other = null;
if (process.env.NODE_ENV === 'development') {
other = require('./webpack.dev.config');
} else {
other = require('./webapack.prod.config');
}
module.exports = merge(base, other);
webpack.base.config.js
- базовая конфигурация
-
webpack.DefinePlugin
определить переменные среды
基本配置...
plugins: [
new webpack.DefinePlugin({
__isDevelopment__: JSON.stringify(process.env.NODE_ENV == 'development')
})
]
webpack.dev.config.js
- к
output
Например, если параметры среды разработки и производственной среды различаются, он будет перезаписан.webpack.base.config.js
конфигурация внутри
const path = require('path');
module.exports = {
output: {
path: path.resolve('./dist'),
filename: "[name].dev.[hash:2].js"
}
};
webpack.prod.config.js
- (к
output
Например)
const path = require('path');
module.exports = {
output: {
path: path.resolve('./dist'),
filename: "[name].prod.[hash:8].js"
}
};
base.js
- в файле конфигурации
webpack.DefinePlugin
Определенные переменные (__isDevelopment__
), который можно получить в файле входа и других файлах, на которые ссылается файл входа__isDevelopment__
значение
let env = null;
if (__isDevelopment__) {
env = 'dev';
} else {
env = 'prod';
}
module.exports = env;
index.js
let env = require('./base.js');
if (__isDevelopment__) {
console.log('dev');
} else {
console.log('prod');
}
console.log('env', env);
/*
prod
env prod
*/
3 note
webpack.DefinePlugin
Причина переноса строки с помощью JSON.stringify при определении значения переменной среды заключается в том, что значение переменной среды должно быть строкой, заключенной в двойные кавычки, а значение JSON.stringify('production') точно равно равно «производству»
Семь CDN
CDN также называют сетью распространения контента.Размещая ресурсы по всему миру, пользователи могут получать ресурсы с ближайшего к пользователю сервера по принципу близости при доступе, тем самым ускоряя скорость получения ресурсов.
- HTML-файлы не кешируются, они размещаются на вашем собственном сервере, кеш вашего собственного сервера отключается, а URL-адрес статического ресурса становится адресом, указывающим на CDN-сервер
- Статические файлы JavaScript, CSS, изображения и другие файлы включают CDN и кеш, а также имена файлов со значениями HASH.
- Чтобы загружать параллельно без блокировки, выделяйте разные статические ресурсы на разные CDN-серверы.
Встряхивание восьмого дерева
1 action
Tree Shaking можно использовать для отсеивания неиспользуемого мертвого кода в JavaScript.
2 useage
- Он основан на статическом модульном синтаксисе ES6, таком как импорт и экспорт через импорт и экспорт.
- Не компилируйте модули ES6
use: {
loader: 'babel-loader',
query: {
presets: [
[
"env", {
modules: false //含义是关闭 Babel 的模块转换功能,保留原本的 ES6 模块化语法
}
],
"react"
]
}
},
3 note
Обратите внимание, что он основан на статическом модульном синтаксисе ES6, таком как импорт и экспорт через импорт и экспорт. То есть, если код проекта работает в среде, не поддерживающей синтаксис es6, Tree Shake не имеет смысла.
9 Извлечь общедоступный код
1 Зачем вам нужно извлекать публичный код
Большой веб-сайт состоит из нескольких страниц. Каждая страница будет содержать много общего кода, поскольку использует один и тот же стек технологий и код стиля. Если включить их все, возникнут проблемы.
Одни и те же ресурсы загружаются повторно, что приводит к трате пользовательского трафика и затрат на сервер; Ресурсы, которые необходимо загрузить для каждой страницы, слишком велики, что приводит к медленной загрузке первой страницы веб-страницы и влияет на взаимодействие с пользователем. Если общий код можно извлечь в отдельный файл для загрузки, его можно оптимизировать, что может уменьшить трафик передачи по сети и снизить затраты на сервер
2 Как извлечь
1) Классификация
Разные типы файлов имеют разные блоки кода после упаковки:
- Базовая библиотека классов для долгосрочного кэширования
- Общий код между страницами
- Отдельные файлы для каждой страницы
2) usage
webpack.config.js
optimization: {
splitChunks: {
cacheGroups: {
commons: {// 页面之间的公用代码
chunks: 'initial',
minChunks: 2,
maxInitialRequests: 5, // The default limit is too small to showcase the effect
minSize: 0 // This is example is too small to create commons chunks
},
vendor: {// 基础类库
chunks: 'initial',
test: /node_modules/,
name: "vendor",
priority: 10,
enforce: true
}
}
}
},
./src/pageA.js
require('./utils/utility1.js');
require('./utils/utility2.js');
require('react');
./src/pageB.js
require('./utils/utility2.js');
require('./utils/utility3.js');
./src/pageC.js
require('./utils/utility2.js');
require('./utils/utility3.js');
utils/utility1.js
module.exports = 1;
utils/utility2.js
module.exports = 2;
utils/utility3.js
module.exports = 3;
упакованный результат
Сгенерированные результаты трех вышеуказанных кодов следующие:
Подъем с десятью сферами
1 action
Scope Hoisting может уменьшить размер файлов кода, упакованных Webpack, и ускорить их работу.Это также переводится как «подъем объема» и представляет собой новую функцию, представленную в Webpack3.
- Меньший размер кода, потому что объявления функций генерируют много кода
- Когда код выполняется, поскольку созданная область действия меньше, накладные расходы памяти также уменьшаются hello.js
2 useage
package.json
"build": "webpack --display-optimization-bailout --mode development",
webpack.config.js
plugins: [
new ModuleConcatenationPlugin()
],
./h.js
export default 'scope hoist'
./index.js
import str from './h.js'
console.log(str);
3 note
Необходимо использовать синтаксис ES6, иначе он не работает (
--display-optimization-bailout
параметры будут запрошены)
Разделение одиннадцати кодов
Разделение кода — одна из самых ярких особенностей webpack. Эта функция разделяет код на разные пакеты, которые затем можно загружать по запросу или параллельно. Существует три распространенных метода разделения кода:
- Начальная точка входа: используйте конфигурацию входа для ручного разделения кода.
- Предотвращение дублирования: используйте splitChunks для дедупликации и разделения фрагментов.
- Динамический импорт: разделение кода с помощью встроенных вызовов функций модулей.
О точке входа и предотвращении повторов было сказано выше, остановимся на динамическом импорте.
1 action
Пользователю нужно только загрузить код, соответствующий той функции, которую пользователю необходимо использовать в данный момент, то есть так называемая загрузка по требованию.При оптимизации загрузки по требованию для одностраничных приложений обычно соблюдаются следующие принципы. усыновленный:
- Разделите функции сайта, по одному фрагменту для каждой категории
- Непосредственно загружайте функции, необходимые для открытия страницы в первый раз, и показывайте ее пользователю как можно скорее.
- Некоторые функции, которые зависят от большого количества кода, могут быть загружены по запросу.
- Код разделения требует времени для загрузки по запросу
2 usage
- использовать
import(module)
синтаксис - импорт модуля асинхронной загрузки - это синтаксис es7
- Импорт является естественной точкой разделения в веб-пакете.
document.getElementById('play').addEventListener('click',function(){
import('./vedio.js').then(function(video){
let name = video.getName();
console.log(name);
});
});