En tercer lugar, el concepto avanzado de paquete web
1.Concepto de agitación de árboles
La agitación de árboles en el front-end puede entenderse como "agitar" nuestros archivos JS a través de herramientas y "sacudir" el código no utilizado, que es una categoría de optimización del rendimiento. Específicamente, en el proyecto de paquete web, hay un archivo de entrada, que es equivalente a la columna vertebral de un árbol, y el archivo de entrada tiene muchos módulos dependientes, que son equivalentes a ramas. En la situación real, aunque se confía en un determinado módulo, solo se utilizan determinadas funciones. A través de la agitación de árboles, se sacuden los módulos no utilizados, para lograr el propósito de eliminar el código inútil.
Tree Shaking solo es compatible con el módulo ES
¿Cómo configurar?
En entorno de desarrollo
// webpack.config.js
optimization: {
usedExports: true
}
// package.json
"sideEffect": false,
// "sideEffect": ["*.css"] 不希望tree-shaking的配置在这里
En el entorno de producción, configure automáticamente la agitación de árboles
2. Diferenciación y empaquetado de los modos Dev y Prod
En el entorno de desarrollo y el entorno de generación, existen diferencias entre source-map, DevServer, HMR, compresión, etc.
Distinguir el funcionamiento de dos entornos.
package.json
{
"scripts": {
"dev": "webpack-dev-server --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
},
}
Cree dos nuevos archivos webpack.dev.js y webpack.prod.js
¡Pero hay mucho del mismo código!
Resolver extracción de piezas públicas
Extraiga la parte común a webpack.common.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: {
publicPath: '/',
filename: '[name].js',
path: path.join(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
targets: {
edge: '17',
firefox: '60',
chrome: '67',
safari: '11.1'
}
}
]
]
}
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin()
],
};
Instalar webpack-merge
npm install webpack-merge -D
Reescribe webpack.prod.js
const {
merge } = require('webpack-merge');
const commonConfig = require('./webpack.common.js');
const prodConfig = {
mode: 'production'
};
module.exports = merge(commonConfig, prodConfig);
Reescribe webpack.dev.js
const webpack = require('webpack');
const {
merge } = require('webpack-merge');
const commonConfig = require('./webpack.common.js');
const devConfig = {
mode: 'development',
devtool: 'source-map',
devServer: {
contentBase: './dist'
// hot: true,
// hotOnly: true
},
plugins: [new webpack.HotModuleReplacementPlugin()],
optimization: {
usedExports: true
}
};
module.exports = merge(commonConfig, devConfig);
3.Webpack 和 División de código
División de código
En el pasado, para reducir las solicitudes HTTP, generalmente empaquetamos todo el código en un solo archivo JS. Sin embargo, si el tamaño del archivo JS es muy grande, la ganancia no vale la pena perder.
En este momento, también podríamos dividir todo el código en una sola pieza y cargarlo cuando se necesite una determinada pieza de código; también puede usar el caché del navegador y, si lo usa la próxima vez, puede leerlo directamente desde el cache. Obviamente, este enfoque puede acelerar la velocidad de carga de nuestras páginas web.
Entonces, Code Splitting en realidad está dividiendo el código en muchos, muchos fragmentos .
Configuración
optimization: {
splitChunks: {
chunks: 'all'
}
}
Luego generará main.js y vendors ~ main.js
Código asincrónico
function getComponent() {
return import('lodash').then(({
default: _ }) => {
var element = document.createElement('div');
element.innerHTML = _.join(['Dell', 'Lee'], '-');
return element;
});
}
getComponent().then(element => {
document.body.appendChild(element);
});
La segmentación de código no tiene nada que ver con el paquete web. Hay dos formas de implementar la segmentación de código en el paquete web.
1. Código síncrono: solo es necesario realizar la configuración de optimización en webpack.common.js
2. Código asincrónico (importación): el código asincrónico, sin ninguna configuración, dividirá automáticamente el código
4. Detalles de configuración del parámetro SplitChunkPlugin de segmentación de código
Configuración de SplitChunkPlugin
Notas mágicas
return import(/* webpackChunkName: "lodash" */'lodash')
Esto generará el archivo vendor ~ lodash.js
El nombre del archivo generado por el paquete es el mismo que el nombre especificado
optimization: {
splitChunks: {
cacheGroups: {
vendors: false,
default: false
}
}
}
asignación predeterminada
module.exports = {
//...
optimization: {
splitChunks: {
// chunks:async只对异步代码进行代码分割,all会同步异步都分割
// 我们打包一个同步代码块,会寻找vendors配置,如果在node_modules中,会进行分割
chunks: 'async',
// 大于30kb,进行代码分割
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
}
}
}
}
};
Carga diferida Carga diferida, ¿qué es un fragmento?
Carga diferida: carga un módulo de forma asincrónica a través de import ()
import () devuelve un tipo de promesa
function getComponent() {
return import(/* webpackChunkName: "lodash-dj" */ 'lodash').then(
({
default: _ }) => {
var element = document.createElement('div');
element.innerHTML = _.join(['Dell', 'Lee'], '-');
return element;
}
);
}
document.addEventListener('click', () => {
getComponent().then(element => {
document.body.appendChild(element);
});
});
async aguardar reescribir
async function getComponent() {
const {
default: _ } = await import(
/* webpackChunkName: "lodash-dj" */ 'lodash'
);
var element = document.createElement('div');
element.innerHTML = _.join(['Dell', 'Lee'], '-');
return element;
}
document.addEventListener('click', async () => {
const element = await getComponent();
document.body.appendChild(element);
})
pedazo
Cada archivo js generado por el empaquetado se llama fragmento
// 简易配置代码分割,交给webpack自动处理
optimization: {
splitChunks: {
chunks: 'all',
}
}
6. Análisis de embalaje, precarga, precarga
Análisis de paquetes
# 输出打包信息到 stats.json
webpack --profile --json > stats.json --config webpack.dev.js
Uso de la herramienta Webpack-bundle-analyzer
Instalar en pc
npm install --save-dev webpack-bundle-analyzer
Uso (como complemento)
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
plugins: [
new BundleAnalyzerPlugin()
]
Una vez completado el empaque, abra automáticamente 127.0.0.1:8888 para ver el análisis
Precarga 和 Precarga
Referencia al texto original: hablar sobre la precarga y la precarga en el paquete web
Documento oficial: módulo de precarga / precarga
Presione en el navegador Ctrl + Shift + P
e ingrese en el cuadro de diálogo emergentecoverage
Desde el cuadro rojo, puede ver la utilización del archivo cargado actualmente en la página actual
A través de la carga asincrónica, mejore la utilización del código, al cargar la página actual, cargue de forma asincrónica código innecesario
Ahora vemos por qué webopack quiere usar chunks: 'async'
una configuración predeterminada.
El enfoque de la optimización del paquete web es el uso del código en lugar del almacenamiento en caché. No tiene sentido usar el almacenamiento en caché para optimizar. Solo mejorando de forma asincrónica la utilización del código se puede mejorar en gran medida el rendimiento del sitio web.
Algunos amigos pueden preguntarse si pueden cargar estos archivos primero cuando la red está inactiva después de cargar la página . Es realmente inteligente. Esta es la precarga y la precarga de la que hablaré a continuación.
-
Precarga
El uso es relativamente simple, es decir, delante del archivo que se va a cargar de forma asincrónica, además
/* webpackPrefetch: true */
del comentario mágico.Podemos escribir código que requiera interacción para ser utilizado en componentes asincrónicos.
document.addEventListener('click', () => { import(/* webpackPrefetch: true */ './click.js').then(({ default: func}) => { func(); }) });
El 0.js generado es click.js después del empaquetado. Se puede ver que 0.js se ha cargado antes de que se haga clic en la página en el tiempo libre después de que se cargue la página. Cuando se hace clic en la página, se lee directamente 0.js de la caché, por lo que el tiempo es muy corto.
-
¿Cuál es la diferencia entre precarga y precarga?
La mayor diferencia entre los dos es que la precarga se carga cuando el ancho de banda está libre después de que se carga el código central, mientras que la precarga se carga junto con el archivo de código central.
Por lo tanto, es más apropiado utilizar Prefetching para cargar archivos asincrónicos.
7. Segmentación de código de archivos CSS
8. Paquete web y caché de caché del navegador
entorno de producción
output: {
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].js'
}
Mientras no necesitemos el código fuente, el valor del archivo no cambiará y el usuario utilizará la caché local para la segunda visita.
Cambios en el código fuente, cambios en el valor hash
Es propicio para la optimización de volver a poner el paquete en línea
9.
Libro corto: calce (calce) compatible con empaquetado webpack