1. webpack4 -- базовая конфигурация
1. Инициализируйте конфигурацию
mkdir webpack4
cd webpack4
mkdir demo1
cd demo1
npm init -y 或 npm init
Структура каталогов
webpack4
├── webpack4/demo1
│ └── webpack4/demo1/package.json
└── webpack4/README.md
-
Установить веб-пакет
npm install webpack --save-dev
-
Установите указанную версию веб-пакета
npm install --save-dev webpack@<version>
-
версия webpack 4+, также необходимо установить webpack-cli
npm install webpack-cli --save-dev
-
npx webpack -v
: просмотреть версию веб-пакета -
npx webpack-cli -v
: Посмотреть версию webpack-cli
Рекомендуется установить webpack и webpack-cli локально На момент написания этого блога последняя версия webpack: 4.30.0, которая также используется в этой статье для изучения webpack4.
Создайте новый каталог src в каталоге demo1 и создайте новый index.js в каталоге src.
mkdir src
cd src
touch index.js
структура каталогов demo1
demo1
├── demo1/package.json
├── demo1/package-lock.json
└── demo1/src
└── demo1/src/index.js
Добавьте код в index.js, например:
//index.js
let demo='webpack4'
console.log(demo)
webpack4 может быть упакован с нулевой конфигурацией, а webpack4 по умолчанию упаковывает файл index.js в каталог src.
беги сейчасnpx webapck
, вы можете увидеть каталог dist в каталоге demo1, в каталоге dist есть файл main.js, это запакованный файл, откройте поиск, чтобы увидетьconsole.log(demo)
, что указывает на то, что index.js упакован в main.js.
2. Простая настройка webpack4
существуетdemo1
новый каталогwebpack
конфигурационный файлwebpack.config.js
настроитьwebpack
--webpack.config.js
const path = require('path')
module.exports={
//mode development: 开发环境 production:生产环境
mode: 'development',
//entry 入口文件配置
entry: {
index: './src/index.js'
},
//打包完成后文件输出位置配置
output: {
//filename 设置打包后文件的名字
//如果不设置filename,则文件的名字跟入口文件路径的属性名一样
filename: 'bundle.js',
//path 设置打包完成后文件输出路径
path: path.resolve(__dirname,'dist')
}
}
бегатьnpx webpack
Заказnpx webpack
Эквивалентноnpx webpack --config webpack.config.js
когдаwebapck
Файл конфигурации называетсяwebpack.config.js
можно опустить, когда--config *.js
, выполнить напрямуюnpx webpack
ОК, иначе выполнитьnpx webpack --config 配置文件名
.
Смотрите, что в каталоге dist естьbundle.js
, указывая на то, что конфигурация веб-пакета верна.
существуетpackage.json
настроить «скрипт» в
"scripts": {
"build": "webpack"
}
Добавить к"build": "webpack"
,бегатьnpm run build
Эффект эквивалентен выполнениюnpx webpack
Заказ.
Настройте объект модуля webpack.config.js
Использование загрузчика
file-loader
использование
Установить
file-loader
npm i file-loader --save-dev
webpack.config.js
const path = require('path')
module.exports={
//mode development: 开发环境 production:生产环境
mode: 'development',
//entry 入口文件配置
entry: {
index: './src/index.js'
},
//打包完成后文件输出位置配置
output: {
//filename 设置打包后文件的名字
//如果不设置filename,则文件的名字跟入口文件路径的属性名一样
filename: 'bundle.js',
//path 设置打包完成后文件输出路径
path: path.resolve(__dirname,'dist')
},
module: {
rules:[
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]', //对打包后的图片命名
outputPath: 'images/' //打包后图片输出的位置 dist\images
}
}
}
]
}
}
Создайте новую папку с изображениями в каталоге src для хранения изображений.
Изменить index.js
//index.js
//import导入图片
import image from './images/11.png'
let img=new Image()
img.src=image
document.body.append(img)
бегатьnpm run build
Структура каталогов выглядит следующим образом
demo1
├── demo1/dist
│ ├── demo1/dist/bundle.js
│ ├── demo1/dist/images
│ │ └── demo1/dist/images/11.png
│ └── demo1/dist/index.html
├── demo1/package.json
├── demo1/package-lock.json
├── demo1/src
│ ├── demo1/src/images
│ │ └── demo1/src/images/11.png
│ └── demo1/src/index.js
└── demo1/webpack.config.js
Каталог изображений и изображения появляются в каталоге dist, создайте index.html, импортируйте файл js и откройте его в браузере, чтобы увидеть изображения.
url-loader
использование
url-loader
Установитьnpm i url-loader -D
url-loader
Роль очень похожа на роль «загрузчика файлов».
webpack.config.js
module: {
rules:[
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]', //对打包后的图片命名
outputPath: 'images/', //打包后图片放的位置dist\images
limit: 20480
//1024 == 1kb
//小于20kb时打包成base64编码的图片否则单独打包成图片
}
}
}
]
}
}
limit
Атрибут: когда размер изображения больше, чем значение атрибута, оно упаковывается как изображение и выводится в каталог изображений, в противном случае оно упаковывается в изображение в кодировке base64 и внедряется в bundle.js.
Поскольку изображение в кодировке base64 приводит к увеличению размера файла пакета, изображение упаковывается в изображение в кодировке base64, когда изображение относительно небольшое, а отдельное изображение упаковывается в одно изображение, когда изображение относительно большое.
правильноcss
а такжеscss
упаковка
Установите соответствующий загрузчик
npm i css-loader style-loader -D
npm i node-sass sass-loader -D
npm i postcss-loader -D
npm i autoprefixer -D
postcss-loader
а такжеautoprefixer
Может автоматически добавлять префикс с использованием процесса упаковки в
Создайте новый в корневом каталоге demo1postcss.config.js
, конфигурация следующая
//postcss.config.js
module.exports={
plugins: [
require('autoprefixer')
]
}
существуетwebpack.config.js
документmodule.rules
Добавить конфигурацию в массив
module:{
rules:[
{
test: /\.css$/,
use:[
'style-loader',
'css-loader',
'postcss-loader'
//加前缀 npm i autoprefixer -D
//在项目根目录下配置postcss.config.js文件
]
},
{
test: /\.scss$/,
use:[
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
//importLoaders
//用于配置css-loader作用于@import的资源之前有多少个loader先作用于@import的资源
}
},
'postcss-loader',
'sass-loader'
]
}
]
}
существуетdemo1
изsrc
под новымcss
папка, вcss
новая папкаstyle.css
а такжеindex.scss
документ.
index.scss
body{
border: 1px solid red;
width: 300px;
height: 300px;
img{
width: 100px;
height: 100px;
border-radius: 10%;
transform: translate(100px,100px);
}
}
style.css
body{
border-radius: 10%;
}
index.js
//index.js
import image from './images/11.png'
import './style.css'
import './index.scss'
let img=new Image()
img.src=image
document.body.append(img)
бегатьnpm run build
, создайте новый index.html в каталоге dist, импортируйте файл js и откройте его в браузере, чтобы увидеть эффект, указывающий на то, что упаковка выполнена успешно.
модульность css
Модульность CSS, чтобы избежать взаимодействия между стилями страницы
существуетwebpack.config.js
серединаcss-loader
Добавить кmodules: true
//webpack.config.js
module:{
rules: [
{
test: /\.css$/,
use:[
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
},
'postcss-loader'
//加前缀 npm i autoprefixer -D
//在项目根目录下配置postcss.config.js文件
]
},
{
test: /\.scss$/,
use:[
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
//importLoaders
//用于配置css-loader作用于@import的资源之前有多少个loader先作用于@import的资源
modules: true //加载css模块化打包,避免样式文件之间相互影响
}
},
'postcss-loader',
'sass-loader'
]
}
]
}
Изменить index.js
.img
Это имя класса, которое нужно заранее прописать в файле стилей.
//index.js
import image from './images/11.png'
import style from './css/style.css'
// import style from './css/index.scss'
let img=new Image()
img.src=image
//style.img .img是scss文件中写好的类名
img.classList.add(style.img)
document.body.append(img)
index.scss
body{
border: 1px solid red;
width: 300px;
height: 300px;
img{
width: 100px;
height: 100px;
border-radius: 10%;
transform: translate(100px,100px);
}
.img{
border: 10px solid royalblue;
}
}
style.css
body{
border-radius: 10%;
}
body .img{
border: 10px solid yellow;
}
результат
Вы можете видеть, что класс добавлен, а имя класса представляет собой строку более сложных строк, чтобы этот стиль не влиял на другие элементы.
2. Далее настраиваем webpack4, удобнее изучить webpack4
Эта часть в основном предназначена для того, чтобы научиться использоватьhtml-webpack-plugin
а такжеclean-webpack-plugin
Плагины, в основном для того, чтобы научиться настраиватьdevServer
А также использовать функцию горячей замены модуля в webpack.
Первый вwebpack4
новый каталогdemo2
Папка будетdemo1
Скопируйте все в каталоге вdemo2
середина
В предыдущей части мы вручную создали index.html в каталоге dist, чтобы импортировать js-файлы для просмотра результатов упаковки, что было бы очень хлопотно. мы можем использоватьhtml-webpack-plugin
Чтобы автоматически создавать index.html и автоматически импортировать упакованные файлы, вы можете напрямую открыть полученный HTML-файл, чтобы увидеть структуру упаковки.
1.html-webpack-plugin
использование
Установить
npm i html-webpack-plugin -D
существуетwebpack.config.js
Настройте элемент конфигурации плагинов в
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
module.exports={
//mode development: 开发环境 production:生产环境
mode: 'development',
//entry 入口文件配置
entry: {
index: './src/index.js'
},
//打包完成后文件输出位置配置
output: {
//filename 设置打包后文件的名字
//如果不设置filename,则文件的名字跟入口文件路径的属性名一样
filename: 'bundle.js',
//path 设置打包完成后文件输出路径
path: path.resolve(__dirname,'dist')
},
module: { },
plugins: [
new htmlWebpackPlugin({
template: './index.html'
})
]
}
Создайте новый index.html в каталоге demo2 в качестве шаблона.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板</title>
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="bundle.js"></script></body>
</html>
бегатьnpm run build
, вы можете видеть, что index.html автоматически создается в каталоге dist, и файлы js также автоматически импортируются
2.clean-webpack-plugin
использование
Каждый раз, когда вы упаковываете сгенерированный каталог dist, если вы изменяете код один раз, вам придется один раз удалить каталог dist, что очень хлопотно.clean-webpack-plugin
Автоматически очищать каталог dist перед каждой упаковкой.
Установить
npm i clean-webpack-plugin -D
существуетwebpack.config.js
изplugins
Конфигурация выглядит следующим образом
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const cleanWebpackPlugin = require('clean-webpack-plugin')
module.exports={
//mode development: 开发环境 production:生产环境
mode: 'development',
//entry 入口文件配置
entry: {
index: './src/index.js'
},
//打包完成后文件输出位置配置
output: {
//filename 设置打包后文件的名字
//如果不设置filename,则文件的名字跟入口文件路径的属性名一样
filename: 'bundle.js',
//path 设置打包完成后文件输出路径
path: path.resolve(__dirname,'dist')
},
module: { },
plugins: [
new htmlWebpackPlugin({
template: './index.html'
}),
new cleanWebpackPlugin()
]
}
бегатьnpm run build
, можете проверить сами, файлы в каталоге dist будут удаляться перед каждой упаковкой.
3.entry
а такжеoutput
Многовходовая конфигурация
module.exports={
//mode development: 开发环境 production:生产环境
mode: 'development',
//entry 入口文件配置
entry: {
index: './src/index.js',
main: './src/index.js'
},
//打包完成后文件输出位置配置
output: {
//filename 设置打包后文件的名字
//如果不设置filename,则文件的名字跟入口文件路径的属性名一样
// 占位符
filename: '[name].js',
//path 设置打包完成后文件输出路径
path: path.resolve(__dirname,'dist')
},
}
Когда есть несколько записей, их необходимо изменить.filename
Стоимость недвижимости[name].js
бегатьnpm run build
, он будет создан в каталоге distindex.js
а такжеmain.js
4. Конфигурацияdevtool
Devtool определяет отношение сопоставления между исходным кодом и упакованным кодом, что удобно для отладки кода.
Рекомендуемая среда разработки: Cheap-module-eval-source-map Рекомендуется для производственной среды: Cheap-module-source-map
Для конкретного содержания devtool, пожалуйста, обратитесь к:Документация: devtool
module.exports={
devtool: 'cheap-module-eval-source-map',
//开发环境推荐: cheap-module-eval-source-map
//生产环境推荐: cheap-module-source-map
}
5. КонфигурацияdevServer
Установить
webpack-dev-server
npm i webpack-dev-server -D
Добавьте следующее в webpack.config.js
module.exports={
devServer: {
contentBase: './dist',
// open: true, //自动打开浏览器
// port: 8080, //默认8080
}
}
Исправлятьpackage.json
изscript
,Добавить к"start": "webpack-dev-server"
"scripts": {
"start": "webpack-dev-server"
},
воплощать в жизньnpm run start
После открытия браузера вы можете увидеть эффект, когда мы изменим код, страница снова обновится.
Иногда мы хотим, чтобы страница обновляла только ту часть, которую мы изменили, а не обновляла страницу, поэтому нам нужно включить функцию горячей замены модуля webpack.
6. Включите функцию горячей замены модулей webpack.
Сначала измените index.js
import './css/style.css'
var btn = document.createElement('button')
btn.innerHTML='新增'
document.body.appendChild(btn)
btn.onclick=function(){
var div=document.createElement('div')
div.innerHTML='items'
document.body.appendChild(div)
}
Измените style.css и удалите index.scss.
//style.css
body{
background: yellow;
}
div:nth-of-type(odd){
background: chartreuse;
font-size: 18px;
}
в webpack.config.js
Представьте веб-пакет:const webpack=require('webpack')
Добавьте следующее содержимое:
const webpack=require('webpack')
module.exports={
plugins: [
new webpack.HotModuleReplacementPlugin() //启用HMR
],
devServer: {
contentBase: './dist',
// open: true, //自动打开浏览器
// port: 8080,
hot: true, //启用webpack的热模块替换功能
hotOnly: true
//devServer.hot在没有页面刷新的情况下启用热模块替换作为构建失败时的后备
}
}
hot:true
включитьHotModuleReplacementPlugin
(ХМР)
воплощать в жизньnpm run start
, После открытия браузера измените цвет фона div, изменится только измененное место, но страница не обновится.
Создайте новый number.js в каталоге src demo2.
number.js
var number=function(){
var div=document.createElement('div')
div.setAttribute("id","number")
div.innerHTML=103
document.body.appendChild(div)
}
export default number
Изменить index.js
import number from './number'
number()
бегатьnpm run start
, откройте его в браузере, чтобы увидеть результат, а затем измените содержимое в number.js, но страница не отображает измененное содержимое
Это связано с тем, что реализация горячей замены модуля немного отличается при импорте js-файлов.
Для достижения эффекта горячей замены модуля в js необходим код if(module.hot){}, иначе даже при изменении кода страница не обновится, а модифицированное место будет изменено на странице.
Стиль CSS, потому что CSS-погрузчик уже реализовал часть If (Module.hot) {}, нет необходимости реализовывать эту часть отдельно.
Измените index.js еще раз
import number from './number'
number()
if(module.hot){
module.hot.accept('./number.js',function(){
number()
document.body.removeChild(document.getElementById('number'))
})
}
бегатьnpm run start
, откройте его в браузере, чтобы увидеть результат, затем измените содержимое в number.js и обнаружите, что на странице отображается измененное содержимое.
3. Используйте Babel для обработки файлов js
Babel— это широко используемый транскодер, который может преобразовывать код ES6 в код ES5 для выполнения в существующих средах.
Babel разделен на три этапа: анализ, преобразование и генерация.
Сам Babel не имеет никакой функции преобразования, он разлагает функцию преобразования на один за другимplugin
в. Поэтому, когда мы не настраиваем никаких плагинов, послеBabel
Выходной код такой же, как и входной.
Использование плагина Babel
-
Добавьте имя плагина в файл конфигурации: создайте в корневом каталоге проекта
.babelrc
файл конфигурации илиwebapck.config.js
конфигурации, обычно в.babelrc
в конфигурации. -
Установить с помощью npm install xxx
Конфигурационный файл Babel.babelrc
, хранящийся в корневом каталоге проекта. Первым шагом в использовании Babel является настройка этого файла.
Этот файл используется для установки правил транскодирования и плагинов.Основной формат выглядит следующим образом.
{
"presets": [],
"plugins": []
}
Краткое введение в Babel
preset
Пресет — это набор плагинов.@babel/preset-env
Коллекция плагинов, содержащая все переводы с ES6 на ES5.
core-js
Преобразование некоторых встроенных классов (Promise, Symbols и т. д.) и статических методов (Array.from и т. д.).
@babel/core
Он существует как ядро Babel, и все основные API Babel находятся в этом модуле.
babel-loader
babel-loader
Используется в webpack, это коммуникационный мост между webpack и Babel.
Введение в @babel/polyfill
@babel/preset-env
Переводить только по умолчаниюjs
синтаксис без транспиляции новогоAPI
,НапримерIterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise
и другие глобальные объекты, а также некоторые методы, определенные для глобального объекта (например,Object.assign
) Не будет переведен. Тогда вы должны использовать@babel/polyfill
(интегрировано внутриcore-js
а такжеregenerator
).
При использовании увеличивать перед запуском всего кодаimport "@babel/polyfill"
или вwebpack.config.js
Входная конфигурация
module.exports = {
entry: ["@babel/polyfill", "./app/js"],
}
Поэтому должен@babel/polyfill
так какdependencies
вместоdevDependencies
У @babel/polyfill есть два основных недостатка:
1. Используйте@babel/polyfill
Необходимо выполнить некоторую дополнительную настройку, и пакет будет введен по мере необходимости, в противном случае он будет@babel/polyfill
Внедрение всего в код приведет к очень большому пакету.
2.@babel/polyfill
загрязняет глобальные переменные.
Babel7
Основное изменение заключается в том, чтоnpm package
изменить имя, положить всеbabel-*
переименован в@babel/*
,Например:
-
babel-polyfill
переименован в@babel/polyfill
-
babel-preset-env
переименован в@babel/preset-env
Использование Babel в веб-пакете
Сначала осуществите перевод грамматики ES6
Создайте новую папку demo3 в каталоге webpack4 и скопируйте все из каталога demo2 в demo3.
Установитьbabel-loader、 @babel/core、@babel/preset-env
npm i babel-loader -D
npm i @babel/core -D
npm i @babel/preset-env -D
babel-loader@8
необходимо установить@babel/core7.x
Версия.
Настроено в webpack.config.js
module.exports={
module: {
rules:[
{
test: /\.js$/,
exclude: /node_modules/,
use:{
loader: 'babel-loader',
options:{
presets: [
["@babel/preset-env",{
//targets:表示编译出的代码想要支持的浏览器版本
targets: {
chrome: "67"
}
}]
]
}
}
}
]
}
}
воплощать в жизньnpm run build
илиnpx webpack
Вы можете увидеть упакованные файлы в каталоге dist, но переведен только синтаксис ES6, а новый API ES6 не переведен, поэтому нам нужно настроить@babel/polyfill
решить эту проблему.
Установить
@babel/polyfill
npm i @babel/polyfill --save
существуетindex.js
введен в@babel/polyfill
index.js
//index.js
import '@babel/polyfill'
let arr=[
new Promise(()=>{}),
new Promise(()=>{}),
2
]
arr.map((item)=>{
console.log(item)
})
представлять@babel/polyfill
Раньше размер main.js составлял 29,5 КБ.
представлять@babel/polyfill
После размера 1 МБ Main.js
Примечание. Приведенные выше сравнения не учитываютtargets
В случае с этим вариантом, поскольку почти все браузеры поддерживают ES6, в данном случае@babel/preset-env
Код не будет обработан.
Это потому, что@babel/polyfill
Реализация всех API внедряется в файл пакета, но многие из API не используются в коде, поэтому нам нужно изменить конфигурацию и ввести соответствующие API по мере необходимости.
Изменить конфигурацию webpack.config.js
Добавить к"useBuiltIns": "usage"
Позже необходимо установитьcore-js@2
, и добавить"corejs": 2
Элемент конфигурации, в настоящее время существует множество параметров конфигурации, вам необходимо создать новый в корневом каталоге проекта..babelrc
файл, настроить в этом файле.
.babelrc
Конфигурация выглядит следующим образом:
-
"useBuiltIns"
Стоимость свойства"usage"
автоматически вводится, когда@babel/polyfill
, вы должны убедиться, что он был установлен@babel/polyfill
-
"useBuiltIns"
Стоимость свойства"usage"
, вам нужно добавить"corejs": 2
Элемент конфигурации, иначе будет сообщено об ошибке, и потребуется установкаcore-js
сначала удалитьindex.js
серединаimport '@babel/polyfill'
Установить
core-js
npm i --save core-js@2
илиnpm i --save core-js@3
{
"presets": [["@babel/preset-env",{
"useBuiltIns": "usage", //不需要把polly都打包到代码中,根据代码按需转译
// core-js@3和core-js@2二选一
//"corejs": 3, //npm i --save core-js@3
"corejs": 2 //npm i --save core-js@2
}]]
}
Исправлятьwebpack.config.js
,удалятьoptions
объект
module.exports={
module: {
rules:[
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
}
}
воплощать в жизньnpm run build
, размер упакованного файла165KB
Однако он не подходит для использования при разработке библиотек классов или сторонних модулей.@babel/polyfill
, поэтому следующее использование@babel/plugin-transform-runtime
Для решения этой проблемы.
Использование @babel/plugin-transform-runtime, @babel/runtime и @babel/runtime-corejs2
@babel/runtime-corejs2: содержитBabel modular runtime helpers
а такжеregenerator-runtime
так же какcore-js
библиотека.
@babel/runtime: содержитBabel modular runtime helpers
а такжеregenerator-runtime
библиотека.
в элементе конфигурацииcorejs
Значение свойства по умолчанию равноfalse
, при необходимостиPromise
ЖдатьAPI
Для перевода необходимо установить значение атрибута в2
и установить@babel/runtime-corejs2
Установить:
npm i @babel/plugin-transform-runtime -D
npm i --save @babel/runtime
npm i --save @babel/runtime-corejs2
Измените файл .babelrc
{
"plugins": [
["@babel/plugin-transform-runtime",{
"helpers": true,
"regenerator": true,
"useESModules": false,
"corejs": 2
}]
]
}
мы кладемpresets
Элемент конфигурации удаляется, а затемnpm run build
упакованный, неупакованныйmain.js
Посмотреть, хотя переводPromise
, но новый синтаксис ES6 не переносится, например:let
не переведено наvar
.
Так что еще нужно настроитьpresets
,потому что"@babel/preset-env"
Содержит плагины, переводящие весь синтаксис ES6 в ES5.
Снова измените файл .babelrc
{
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/plugin-transform-runtime",{
"helpers": true,
"regenerator": true,
"useESModules": false,
"corejs": 2
}]
]
}
Добавить кpresets
элемент конфигурации, затемnpm run build
упакованный, неупакованныйmain.js
вижу-вижуlet
а стрелочные функции транспилируются в синтаксис ES5.
Четыре,Tree Shaking
использовать
Сначала создайте новую папку demo4 в каталоге webpack4 и скопируйте все содержимое каталога demo3 в demo4.
Tree Shaking
можно использовать для удаленияJavaScript
Мертвый код, который не работает. он зависит от статикиES6
модульный синтаксис, например черезimport
а такжеexport
Импорт и экспорт.
Следует отметить, чтоTree Shaking
Предпосылкой нормальной работы являетсяJavaScript
код должен использоватьES6
модульный синтаксис, потому чтоES6
Модульный синтаксис является статическим, что позволяетWebpack
Что можно легко проанализироватьexport
одеялоimport
проходить.
Следующая настройкаWebpack
ПозволятьTree Shaking
вступить в силу
webpack4
Модульные операторы ES6 сохраняются по умолчанию и не преобразуются Babel.
Исправлять.babelrc
Документ выглядит следующим образом:
//.babelrc
{
"presets": [["@babel/preset-env",{
"useBuiltIns": "usage",
"corejs": 2,
"modules":false //关闭 Babel 的模块转换功能,保留原本的 ES6 模块化语法
//默认是auto,取值还可以是 amd, umd, systemjs, commonjs,auto等
}]]
}
Исправлятьwebapck.config.js
,Добавить к
optimization: {
usedExports: true
}
прибытьmodule.exports{}
середина
module.exports={
mode: 'development',
optimization: {
//开发坏境使用tree shaking时加usedExports: true
usedExports: true
},
}
еще нужно пройтиpackage.json
из"sideEffects"
Атрибут, указывающий веб-пакету, какие модули можно игнорировать, если не установлено значениеfalse
, чтобы сообщить веб-пакету, что он может безопасно удалить неиспользуемыеexport
.
Исправлятьpackage.json
{
"name": "your-project",
"sideEffects": false
}
Создайте новый math.js в src под demo4
index.js
//tree shaking import export
import {cube} from './math.js'
let component = () => {
let element = document.createElement('pre')
element.innerHTML = [
'Hello webpack!',
'2 cubed is equal to ' + cube(2)
].join('\n\n');
console.log(cube)
return element;
}
document.body.appendChild(component());
math.js
export let square= (x) => {
console.log(x)
return x * x;
}
export let cube = (x) => {
console.log(x)
return x * x * x;
}
бегатьnpm run build
, затем откройте упакованный файл js: main.js, чтобы найти следующий текст
/*!*********************!*\
!*** ./src/math.js ***!
\*********************/
/*! exports provided: square, cube */
/*! exports used: cube */
/***/
Из приведенного выше текста видно, чтоTree Shaking
Вступает в силу, но в среде разработки бесполезный код не удаляется, потому что код нужно отлаживать в среде разработки.
Мы определили «мертвый код», который необходимо удалить, однако речь идет не только о его поиске, но и об удалении. Для этого нам нужноmode
Параметры конфигурации установлены наproduction
, удалить объект оптимизации, изменитьdevtool
параметры конфигурации
webpack.config.js
module.exports = {
mode: 'production',
devtool: 'cheap-module-source-map'
}
бегатьnpm run build
, вы можете увидеть, что бесполезный код был удален путем просмотра результатов упаковки.
Пятерки,Develoment
а такжеProduction
Конфигурация для разных сред
Создайте новый demo5 в webpack4 и скопируйте все файлы из demo4 в demo5.
Поскольку в разных средах конфигурация веб-пакета немного отличается, если нам нужно переключаться между разными коммутаторами, мы должны изменить конфигурацию веб-пакета, что очень хлопотно и легко сделать ошибки, поэтому нам нужно разделить файл конфигурации. .
Создайте новую папку сборки в корневом каталоге проекта, а затем создайте новую в папке сборки.webpack.dev.js
,webpack.prod.js
а такжеwebpack.base.js
три файла
webpack.dev.js
: это среда разработкиwebpack.prod.js
: производственная средаwebpack.base.js
: конфигурация, используемая как в среде разработки, так и в производственной среде.
Комбинация этих файлов зависит от подключаемого модуля «webpack-merge».
Установить
npm i webpack-merge -D
webpack.dev.js
//webpack.dev.js
const webpack=require('webpack')
const merge = require('webpack-merge')
const baseConfig=require('./webpack.base')
const devConfig={
mode: 'development',
devtool: 'cheap-module-eval-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin()
],
optimization: {
usedExports: true
},
devServer: {
contentBase: './dist',
// open: true, //自动打开浏览器
// port: 8080,
hot: true, //启用webpack的热模块替换功能
//hotOnly: true
//devServer.hot在没有页面刷新的情况下启用热模块替换作为构建失败时的后备
}
}
module.exports=merge(baseConfig,devConfig)
webapck.prod.js
//webapck.prod.js
const merge = require('webpack-merge')
const baseConfig=require('./webpack.base')
const prodConfig={
mode: 'production',
devtool: 'cheap-module-source-map'
}
module.exports=merge(baseConfig,prodConfig)
Но эти два документа есть много дублированного кода, новыйwebpack.base.js
//webpack.base.js
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const cleanWebpackPlugin = require('clean-webpack-plugin')
module.exports={
entry: {
main: './src/index.js'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname,'dist')
},
module: {
rules:[
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},
{
test: /\.css$/,
use:[
'style-loader',
'css-loader',
'postcss-loader'
]
},
{
test: /\.scss$/,
use:[
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true
}
},
'sass-loader',
'postcss-loader'
]
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
},
plugins: [
new htmlWebpackPlugin({
template: './index.html'
}),
new cleanWebpackPlugin(),
]
}
Исправлятьpackage.json
изscript
:
{
"scripts": {
"dev": "webpack-dev-server --config ./build/webpack.dev.js",
"build": "webpack --config ./build/webpack.prod.js"
},
}
Среда разработки: запуститьnpm run dev
, откройте браузер для доступаhttp://localhost:8080/
вы можете увидеть результат
Производственная среда: запуститьnpm run build
6. Использование плагина SplitChunksPlugin
1. Знакомство с плагином SplitChunksPlugin
webpack 4
УдалитьCommonsChunkPlugin
,заменяетсяSplitChunksPlugin
. Представьте нижеSplitChunksPlugin
Применение.
существуетwebpack4目录
под новымdemo6目录
,Будуdemo5目录
Все файлы копируются вdemo6
середина.
установить Лодаш
npm i lodash --save
существуетpackage.json
Добавить к
"scripts": {
"dev-build": "webpack --config ./build/webpack.dev.js"
}
Исправлятьindex.js
import _ from 'lodash'
console.log(_.join(['lodash', 'babel', 'webpack'], '-'))
бегатьnpm run dev-build
После этого структура каталогов demo6 выглядит следующим образом
demo6
├── demo6/build
│ ├── demo6/build/webpack.base.js
│ ├── demo6/build/webpack.dev.js
│ └── demo6/build/webpack.prod.js
├── demo6/dist
│ ├── demo6/dist/index.html
│ └── demo6/dist/main.js
├── demo6/index.html
├── demo6/package.json
├── demo6/package-lock.json
├── demo6/postcss.config.js
└── demo6/src
└── demo6/src/index.js
В каталоге dist есть только js файл main.js, а в main.js запакована и библиотека lodash.В этом случае файл станет больше и скорость загрузки страницы будет медленнее.Нам нужно запаковать третий библиотека или должны быть упакованы отдельно.Код разделен.
В настоящее время вам нужно использовать плагин, который поставляется с webpack4.SplitChunksPlugin
, по умолчанию это повлияет только на блоки кода, загружаемые по запросу.
существуетwebpack.config.js
Добавить кoptimization.splitChunks.chunks
optimization: {
splitChunks: {
//chunks: all, async, initial.
//async针对异步加载的chunk做切割,initial针对初始chunk,all针对所有chunk。
chunks: 'async'
}
}
бегатьnpm run dev-build
После этого упакованный код не разбивается.
Исправлятьoptimization.splitChunks.chunks
дляall
optimization: {
splitChunks: {
//chunks: all, async, initial.
//async针对异步加载的chunk做切割,initial针对初始chunk,all针对所有chunk。
chunks: 'all'
}
}
бегатьnpm run dev-build
После этого структура каталогов demo6 выглядит следующим образом
demo6
├── demo6/build
│ ├── demo6/build/webpack.base.js
│ ├── demo6/build/webpack.dev.js
│ └── demo6/build/webpack.prod.js
├── demo6/dist
│ ├── demo6/dist/index.html
│ ├── demo6/dist/main.js
│ └── demo6/dist/vendors~main.js
├── demo6/index.html
├── demo6/package.json
├── demo6/package-lock.json
├── demo6/postcss.config.js
└── demo6/src
└── demo6/src/index.js
Вы можете видеть, что в каталоге dist есть еще многоvendors~main.js
документ, описаниеSplitChunksPlugin
Плагин работает
см. далееoptimization.splitChunks
конфигурация по умолчанию
module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
}
-
чанки: указывает, какие чанки будут оптимизированы, необязательный асинхронный, начальный, все, асинхронный для асинхронно загружаемых модулей, начальный для начальных модулей, все для всех модулей
-
minSize: Загружаемый модуль должен быть не менее 30кб перед разбиением
-
minChunks: сгенерировано
chunk
, чанки, разделяющие модуль, должны быть не меньше 1 до разделения -
maxAsyncRequests: максимальное количество параллельных запросов при загрузке по требованию.
-
maxInitialRequests: максимальное количество параллельных запросов в точке входа.
-
AutomaticNameDelimiter: по умолчанию веб-пакет генерирует имя с именем и именем чанка (например, vendors~main.js). Этот параметр указывает разделитель, используемый для сгенерированных имен.
-
Имя: имя сгенерированного куска, если установлено значение true, имя будет сгенерировано на основе комбинации конфигурации группы модуля и кэша.
-
cacheGroups: группы кеша могут наследовать и/или переопределять любые параметры splitChunks.*, однако тест, приоритет и повторное использованиеExistingChunk можно настроить только на уровне группы кеша. Чтобы отключить любую группу кеша по умолчанию, установите для нее значение false.
-
test: модуль, который управляет выбором этой группы кеша
-
приоритет: модуль может принадлежать к нескольким группам кеша, а модуль принадлежит к группе кеша с высоким приоритетом
-
reuseExistingChunk: если текущий фрагмент содержит разделенный модуль, он будет повторно использован вместо создания нового фрагмента.
Как видно из вышеизложенного, конфигурация по умолчанию действительна только для асинхронно загружаемых модулей.
Измените index.js для асинхронной загрузки lodash.
function getComponent(){
return import('lodash').then(({default: _})=>{
var element=document.createElement('div')
element.innerHTML=_.join(['lodash', 'babel', 'webpack'], '-')
return element
})
}
getComponent().then(element=>{
document.body.appendChild(element)
})
беги в это времяnpm run dev-build
Сообщит об ошибке, нужно скачать и установить@babel/plugin-syntax-dynamic-import
npm i @babel/plugin-syntax-dynamic-import -D
добавить в .babelrc
"plugins": ["@babel/plugin-syntax-dynamic-import"]
бежать сноваnpm run dev-build
, на данный момент упаковка выполнена успешно, и структура каталогов выглядит следующим образом
demo6
├── demo6/build
│ ├── demo6/build/webpack.base.js
│ ├── demo6/build/webpack.dev.js
│ └── demo6/build/webpack.prod.js
├── demo6/dist
│ ├── demo6/dist/0.js
│ ├── demo6/dist/index.html
│ └── demo6/dist/main.js
├── demo6/index.html
├── demo6/package.json
├── demo6/package-lock.json
├── demo6/postcss.config.js
└── demo6/src
└── demo6/src/index.js
Вы можете увидеть каталог dist0.js
, представляет собой упакованный файл lodash, иногда мы хотим иметь возможность изменять0.js
имя
Изменить index.js,Добавить к/* webpackChunkName:"lodash" */
function getComponent(){
return import(/* webpackChunkName:"lodash" */'lodash').then(({default: _})=>{
var element=document.createElement('div')
element.innerHTML=_.join(['lodash', 'babel', 'webpack'], '-')
return element
})
}
getComponent().then(element=>{
document.body.appendChild(element)
})
бегатьnpm run dev-build
,Обнаружить0.js
сталиvendors~lodash.js
также можно установитьoptimization.splitChunks.cacheGroups.vendors.name
изменить имя упакованного файла
Исправлятьoptimization.splitChunks
настроить
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
name: 'vendors'
},
default: {
minChunks: 1,
priority: -20,
reuseExistingChunk: true
}
}
}
},
бегатьnpm run dev-build
, обнаружил, что имя упакованного файла становитсяvendors.js
ВышеупомянутоеSplitChunksPlugin
простое использование
Для получения подробной информации, пожалуйста, посетите официальный сайт
Семь, сегментация кода css
MiniCssExtractPlugin
Плагин извлекает CSS в отдельные файлы. Он создает файл CSS для каждого файла JS, который содержит CSS, доступный только в веб-пакете 4.
Создайте новый demo7 в каталоге webpack, скопируйте все файлы из demo6 в demo7 и введите demo7
Установить
npm install --save-dev mini-css-extract-plugin
Официальный сайт предлагает использовать этот плагин в производственной среде, поэтому измените соответствующую конфигурацию webpack.
Первое местоwebpack.base.js
Скопируйте и вставьте конфигурацию загрузчика для обработки css и scss (удалите эту часть в webpack.base.js) вwebpack.prod.js
а такжеwebpack.dev.js
середина.
существуетwebpack.prod.js
введен вconst miniCssExtractPlugin = require('mini-css-extract-plugin')
Соответствующая конфигурация после модификации выглядит следующим образом:
webpack.base.js
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const cleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
entry: {
main: './src/index.js' //对应filename
//入口文件引入的模块,分割打包的名字对应chunkFilename
},
output: {
filename: '[name].js',
chunkFilename: '[name].chunk.js',
path: path.resolve(__dirname, '../dist')
},
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
},
plugins: [
new htmlWebpackPlugin({
template: './index.html'
}),
new cleanWebpackPlugin(),
],
optimization: {
usedExports: true,
splitChunks: {
//chunks: all, async, initial.
//async 只对异步分割有效
// initial同步
//all 要配置cacheGroups
chunks: 'all',
// 引入的包或是库大于30kb才对代码进行分割
minSize: 30000,
maxSize: 0, //没多大意义
minChunks: 1, //当一个模块至少引入多少次时才会进行代码分割
maxAsyncRequests: 5, //同时加载的模块数最多是5个
maxInitialRequests: 3,
automaticNameDelimiter: '~', //打包后的文件名字之间的连接符
name: true,
cacheGroups: { //缓存组
// vendors: false,
vendors: {
//同步 检查是否在node_modules里面
test: /[\\/]node_modules[\\/]/,
priority: -10, //优先级
name: 'vendors'
},
// default: false
default: {
minChunks: 1,
priority: -20,
reuseExistingChunk: true, //如果模块已经打包过了就引用之前打包好的模块
// filename: 'common.js'
}
}
}
}
}
webpack.prod.js
const merge = require('webpack-merge')
const baseConfig=require('./webpack.base')
const miniCssExtractPlugin = require('mini-css-extract-plugin')
const prodConfig={
mode: 'production',
devtool: 'cheap-module-source-map',
module: {
rules: [
{
test: /\.css$/,
use: [
miniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
},
{
test: /\.scss$/,
use: [
miniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true
}
},
'postcss-loader',
'sass-loader'
]
},
]
},
plugins: [
new miniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[name].chunk.css'
})
]
}
module.exports=merge(baseConfig,prodConfig)
webapck.dev.js
const webpack=require('webpack')
const merge = require('webpack-merge')
const baseConfig=require('./webpack.base')
const devConfig={
mode: 'development',
// devtool: 'cheap-module-eval-source-map',
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true
}
},
'sass-loader',
'postcss-loader'
]
},
]
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
// open: true, //自动打开浏览器
// port: 8080,
hot: true, //启用webpack的热模块替换功能
//hotOnly: true
//devServer.hot在没有页面刷新的情况下启用热模块替换作为构建失败时的后备
}
}
module.exports=merge(baseConfig,devConfig)
Следует отметить, что когда мы ранее настраивали встряхивание дерева, мы добавили элемент конфигурации sideEffects в package.json, и нам нужно изменить этот элемент конфигурации как
"sideEffects": [
"*.css"
],
в противном случае пройтиimport './*.css'
Файл css, введенный методом, будет удален.
бегатьnpm run build
, мы видим, что в каталоге dist файлы css разделены отдельно.
Официальный сайт также предоставляет плагин для сжатия файлов css.
Установить
npm i optimize-css-assets-webpack-plugin -D
Изменить webpack.prod.js
//引入
const optimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
//添加
optimization: {
minimizer: [new optimizeCSSAssetsPlugin({})],
},
бежать сноваnpm run build
, откройте упакованный файл css и обнаружите, что файл css сжат.
Для более конкретного использования, пожалуйста, посетите официальный сайт
Код загружен на гитхаб:github:webpack4