webpack5学习笔记
webpack基础
中文官网
https://www.webpackjs.com/
基本使用
- 在当前目录下使用
npm i webpack webpack-cil -D下载webpack需要的包 npx webpack ./src/main.js --mode=production可以将代码编译成生产环境可以运行的代码npx webpack ./src/main.js --mode=development可以将代码编译成开发环境可以运行的代码- 如果根目录下有
webpack.config.js文件就可以直接使用npx webpack打包
核心配置
- entry(入口):指定打包的入口文件。默认为
src/main.js - output(出口):指定打包的出口文件
- loader(加载器):webpack本身只能处理
js、css文件,其他的资源文件需要借助loader、webpack才能解析 - pulgins(插件):扩展webpack功能
- mode(模式):开发模式
development和生产模式production
开发模式下webpack作用
- 解析处理css,字体资源,图片文件资源以及html文件
- 代码质量检查,树立代码规范
处理css样式资源
- 下载
npm i css-loader --save-dev和npm i style-loader -D - 在
main.js文件中引入css文件 - 在
rules中添加规则如下:
rules:[
// loader配置
{
test:/.css$/, // 只检测以.css结尾的文件,
use: [
'style-loader',
'css-loader' // 将css资源编译成commonjs的模块到js中
], // 从下往上解析
}
]
npx webpack打包css文件
处理less资源
- 下载
npm i less-loader --save-dev - 在
main.js文件中引入less文件 - 在
rules中添加规则如下:
rules:[
// loader配置
{
test:/.less$/, // 只检测以.less结尾的文件
use: [
'style-loader',
'css-loader',
'less-loader'
],
}
]
npx webpack打包less文件
处理sass资源:同上
处理stylus资源:同上
处理图片资源
- webpack默认会将图片资源进行转化不用下载任何的
loader资源 - 可以配置图片打包的一些输出结果。比如:将小于10kb的图片转化为base64格式
{
test: /.(png|jpe?g|svg| gif| webg)$/, // 图片格式
type: 'asset',
parser:{
dataUrlCondition: {
// 小于10kb 的转base64
maxSize: 10 * 1024
}
},
配置图片资源的路径
generator:{
// 输入图片名称、路径
// hash8位
filename:'static/imagse/[hash:8][ext][query]'
}
}
自动清空上次打包资源
output: {
// 输出路径。绝对路径
path: path.resolve(__dirname, 'dist'), // __dirname代表当前文件的目录
// js文件打包路径
filename: 'static/js/main.js',
// 自动清空上次打包结果
clean:true,
},
处理字体图标库资源
- 项目中引入字体图标库文件
- 在main中引入字体图标
css文件 - 配置打包路径
{
test: /.(ttf|woff2?)$/,
type: 'asset/resource', // 将文件原封不动进行输出,不会转化为base64
generator: {
filename: "fonts/[hash:8][ext][query]",
}
}
npx webpack打包
处理其他资源如:音视频资源
{
test: /.(mp3 | mp4)$/,
type: 'asset/resource',
generator: {
filename: "fonts/[hash:8][ext][query]",
}
}
处理js资源。
- 将es5转化为es6,兼容性问题。babel
- 代码格式规范。eslint
eslint
-
文件写法:
- .eslintrc.*:位于根目录下
- .eslintrc
- .eslintrc.js
- .eslintrc.json
- 在packjson中eslintconfig即可
-
在webpack使用,可以参考
-
安装
eslint-webpack-plugin和eslint -
在vue.config.vue文件中引入,最后创建文件进行配置即可。
const ESLintPlugin = require('eslint-webpack-plugin'); module.exports = { // ... plugins: [new ESLintPlugin(options)], // ... };
-
-
eslint文件配置
// 配置文件
module.exports = {
extends: ['eslint:recommended'], // 继承eslint规则
env: {
node:true, // 启用node全局变量
browser:true, // 启用浏览器全局变量
},
parserOptions: {
ecmaVersion:6, // es6
sourceType:'module', // es module
},
rules:{
"no-var": 2 // 不能使用var定义变量
}
}
- .
eslintignore为eslint规范忽略文件。在改文件下输入忽略的文件即可。
babel
-
定义:
babel为js代码编译器,可以将es6比较高级的写法转化为向后兼容的代码,以便可以在浏览器中运行。 -
配置文件写法
-
babe.config.*位于根目录babel.config.jsbabel.config.json
-
.babelrc.*位于根目录.babelrc- .
babelrc.js .babelrc.json
-
package.json中babel:不需要创建文件,可以直接编写。
-
-
在webpack使用。参考
-
安装插件
- npm install -D babel-loader @babel/core @babel/preset-env webpack
-
在webpack中加入规则
{ test: /.m?js$/, exclude: /(node_modules|bower_components)/, // 排除的文件名称 use: { loader: 'babel-loader', options: { // 也可以在bable.config文件中写 presets: ['@babel/preset-env'] } } }
-
-
bablel文件配置
// bable 配置文件 module.exports = { // 智能映射,能够编译es6语法 presets: ['@babel/preset-env'], }
自动引入打包后的文件
-
下载插件
npm install --save-dev html-webpack-plugin。参考 -
在webpack文件中引入
const HtmlWebpackPlugin = require('html-webpack-plugin'); const path = require('path'); module.exports = { entry: 'index.js', output: { path: path.resolve(__dirname, './dist'), filename: 'index_bundle.js', }, plugins: [new HtmlWebpackPlugin({ // 模板,以pubilc/index.html为模板创建新的文件 // 新的html文件特点;1.结构和原来一致2.自动引入打包的js文件 template: path.join(__dirname, 'pubilc/index.html') })], };
开发服务器&自动化
因为每次代码需要手动输入指令才能编译代码
-
下载包
npm i webpack-dev-server -D
-
webpack配置
// 开发服务器。不会输出任何资源,在内存中编译打包的 devServer:{ host: 'localhost', // 域名 port: '3000', //端口 open: true, // 是否自动打开浏览器 }, -
启动服务
npx webpack server
生产模式
-
注意:
- 在开发文件中所有的绝对路径都要添加上一级目录。'../'
- 开发环境输入文件的路径可以为空,因为是试内存中进行编译的
- 自动删除dist文件可以为false
-
启动不同的配置文件命令:
npx webpack serve --config ./config/webpack.dev.jsnpx webpack --config ./config/webpack.prod.js
-
在package文件中配置启动文件快捷命令
"scripts": { "start": "npm run dev", "dev": "webpack serve --config ./config/webpack.dev.js", "build":"webpack --config ./config/webpack.prod.js" }, -
开发和生产环境webpack文件具体配置
-
开发
// webpage基本配置 const path = require('path'); const ESLintPlugin = require('eslint-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { // 相对路径 entry: './src/main.js', output: { // 生产环境可以为undefined,没有输出。输出路径。绝对路径 path: undefined, // __dirname代表当前文件的目录 // js文件打包路径 filename: 'static/js/main.js', // 自动清空上次打包结果 // clean:true, }, module: { rules: [ // loader配置 { test: /.css$/, // 只检测以.css结尾的文件, use: [ 'style-loader', 'css-loader' // 将css资源编译成commonjs的模块到js中 ], // 从下往上解析 }, { test: /.less$/, // 只检测以.less结尾的文件, use: [ 'style-loader', 'css-loader', 'less-loader' ], }, { test: /.s[ac]ss$/, // 只检测以.sass结尾的文件, use: [ 'style-loader', 'css-loader', 'less-loader', 'sass-loader' ], }, { test: /.styl$/, // 只检测以.sass结尾的文件, use: [ 'style-loader', 'css-loader', 'less-loader', 'sass-loader', 'stylus-loader' ], }, { test: /.(png|jpe?g|svg| gif| webg)$/, // 图片格式 type: 'asset', parser:{ dataUrlCondition: { // 小于10kb 的转base64 maxSize: 10 * 1024 } }, generator: { filename: "imgs/[hash:8][ext][query]", } }, { test: /.(ttf|woff2? | mp3 | mp4)$/, // 图片格式 type: 'asset/resource', generator: { filename: "fonts/[hash:8][ext][query]", } }, { test: /.m?js$/, exclude: /(node_modules|bower_components)/, // 排除的文件名称 use: { loader: 'babel-loader', // options: { // presets: ['@babel/preset-env'] // } } } ] }, // 插件 plugins: [ new ESLintPlugin({ context: path.resolve(__dirname, '../src'), }), new HtmlWebpackPlugin({ // 模板,以pubilc/index.html为模板创建新的文件 // 新的html文件特点;1.结构和原来一致2.自动引入打包的js文件 template: path.join(__dirname, '../pubilc/index.html') }) ], // 开发服务器: 不会输出任何资源,在内存中编译打包的 devServer:{ host: 'localhost', // 域名 port: '3000', //端口 open: true, // 是否自动打开浏览器 }, // 模式 mode: 'development' }
-
-
生产
// webpage基本配置 const path = require('path'); const ESLintPlugin = require('eslint-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { // 相对路径 entry: './src/main.js', output: { // 输出路径。绝对路径 path: path.resolve(__dirname, '../dist'), // __dirname代表当前文件的目录 // js文件打包路径 filename: 'static/js/main.js', // 自动清空上次打包结果 clean:true, }, module: { rules: [ // loader配置 { test: /.css$/, // 只检测以.css结尾的文件, use: [ 'style-loader', 'css-loader' // 将css资源编译成commonjs的模块到js中 ], // 从下往上解析 }, { test: /.less$/, // 只检测以.less结尾的文件, use: [ 'style-loader', 'css-loader', 'less-loader' ], }, { test: /.s[ac]ss$/, // 只检测以.sass结尾的文件, use: [ 'style-loader', 'css-loader', 'less-loader', 'sass-loader' ], }, { test: /.styl$/, // 只检测以.sass结尾的文件, use: [ 'style-loader', 'css-loader', 'less-loader', 'sass-loader', 'stylus-loader' ], }, { test: /.(png|jpe?g|svg| gif| webg)$/, // 图片格式 type: 'asset', parser:{ dataUrlCondition: { // 小于10kb 的转base64 maxSize: 10 * 1024 } }, generator: { filename: "imgs/[hash:8][ext][query]", } }, { test: /.(ttf|woff2 |woff | mp3 | mp4)$/, // 图标字体格式 type: 'asset/resource', generator: { filename: "fonts/[hash:8][ext][query]", } }, { test: /.m?js$/, exclude: /(node_modules|bower_components)/, // 排除的文件名称 use: { loader: 'babel-loader', // options: { // presets: ['@babel/preset-env'] // } } } ] }, // 插件 plugins: [ new ESLintPlugin({ context: path.resolve(__dirname, '../src'), }), new HtmlWebpackPlugin({ // 模板,以pubilc/index.html为模板创建新的文件 // 新的html文件特点;1.结构和原来一致2.自动引入打包的js文件 template: path.join(__dirname, '../pubilc/index.html') }) ], // 生产模式不需要 // // 开发服务器: 不会输出任何资源,在内存中编译打包的 // devServer:{ // host: 'localhost', // 域名 // port: '3000', //端口 // open: true, // 是否自动打开浏览器 // }, // 模式 mode: 'production', // 生产模式 }
生产环境Css文件处理
提取Css为单独文件
因为css文件和js文件打包在一起,当js加载时,会创建一个style标签来生成样式,这样会导致出现闪屏现象,体验不好,
应该单独打包css文件,通过link标签引入。
-
下载包:
npm i mini-css-extract-pulgin --save-dev。参考 -
在webpack中配置
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { plugins: [new MiniCssExtractPlugin({ filename: 'css/index.css' // 指定css文件打包后的路径 })], module: { rules: [ { test: /.css$/i, use: [MiniCssExtractPlugin.loader, "css-loader"],// 将所有的style-loader换成这个MiniCssExtractPlugin.loader, }, ], }, };
css兼容性处理
-
下载包:
npm i postcss-loader postcss postcss-preset-env -D。参考 -
webpack 配置。需要在css-loader下面。less-loader上面进行填写
// webpage基本配置 const path = require('path'); const ESLintPlugin = require('eslint-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { // 相对路径 entry: './src/main.js', output: { // 输出路径。绝对路径 path: path.resolve(__dirname, '../dist'), // __dirname代表当前文件的目录 // js文件打包路径 filename: 'static/js/main.js', // 自动清空上次打包结果 clean:true, }, module: { rules: [ // loader配置 { test: /.css$/, // 只检测以.css结尾的文件, use: [ MiniCssExtractPlugin.loader, // 提取css为单独文件 'css-loader', // 将css资源编译成commonjs的模块到js中 { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ [ 'postcss-preset-env', { // 其他选项 }, ], ], }, }, }, ], // 从下往上解析 }, { test: /.less$/, // 只检测以.less结尾的文件, use: [ MiniCssExtractPlugin.loader, 'css-loader', { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ [ 'postcss-preset-env', { // 其他选项 }, ], ], }, }, }, 'less-loader' ], }, { test: /.s[ac]ss$/, // 只检测以.sass结尾的文件, use: [ MiniCssExtractPlugin.loader, 'css-loader', { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ [ 'postcss-preset-env', { // 其他选项 }, ], ], }, }, }, 'less-loader', 'sass-loader' ], }, { test: /.styl$/, // 只检测以.sass结尾的文件, use: [ MiniCssExtractPlugin.loader, 'css-loader', { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ [ 'postcss-preset-env', { // 其他选项 }, ], ], }, }, }, 'less-loader', 'sass-loader', 'stylus-loader' ], }, { test: /.(png|jpe?g|svg| gif| webg)$/, // 图片格式 type: 'asset', parser:{ dataUrlCondition: { // 小于10kb 的转base64 maxSize: 10 * 1024 } }, generator: { filename: "imgs/[hash:8][ext][query]", } }, { test: /.(ttf|woff2 |woff | mp3 | mp4)$/, // 图标字体格式 type: 'asset/resource', generator: { filename: "fonts/[hash:8][ext][query]", } }, { test: /.m?js$/, exclude: /(node_modules|bower_components)/, // 排除的文件名称 use: { loader: 'babel-loader', // options: { // presets: ['@babel/preset-env'] // } } } ] }, // 插件 plugins: [ new ESLintPlugin({ context: path.resolve(__dirname, '../src'), }), new HtmlWebpackPlugin({ // 模板,以pubilc/index.html为模板创建新的文件 // 新的html文件特点;1.结构和原来一致2.自动引入打包的js文件 template: path.join(__dirname, '../pubilc/index.html') }), new MiniCssExtractPlugin({ filename: 'css/index.css', }) ], // 生产模式不需要 // // 开发服务器: 不会输出任何资源,在内存中编译打包的 // devServer:{ // host: 'localhost', // 域名 // port: '3000', //端口 // open: true, // 是否自动打开浏览器 // }, // 模式 mode: 'production', // 生产模式 } -
在package文件中配置css兼容程度,和scripts同级。
"browserslist":[ "ie>=8" ] 开发常见配置 "browserslist":[ // 同时满足 "last 2 versions", // 所有浏览器的最后俩个版本 "> 1%", // 99%浏览器 "not dead" // 版本死的不要 ]就会出现兼容ie 8 的css代码
减少重复代码
// webpage基本配置
const path = require('path');
const ESLintPlugin = require('eslint-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// loaderType为传入的loader类型。less sass
function getStyleLoader(loaderType) {
return [
MiniCssExtractPlugin.loader, // 提取css为单独文件
'css-loader', // 将css资源编译成commonjs的模块到js中
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-preset-env',
{
// 其他选项
},
],
],
},
},
},
loaderType, // 不传就会自动过滤掉
].filter(Boolean) // 将不Boolean自动过滤掉
}
module.exports = {
// 相对路径
entry: './src/main.js',
output: {
// 输出路径。绝对路径
path: path.resolve(__dirname, '../dist'), // __dirname代表当前文件的目录
// js文件打包路径
filename: 'static/js/main.js',
// 自动清空上次打包结果
clean: true,
},
module: {
rules: [
// loader配置
{
test: /.css$/, // 只检测以.css结尾的文件,
use: getStyleLoader(), // 从下往上解析
},
{
test: /.less$/, // 只检测以.less结尾的文件,
use: getStyleLoader('less-loader'),
},
{
test: /.s[ac]ss$/, // 只检测以.sass结尾的文件,
use: getStyleLoader('sass-loader'),
},
{
test: /.styl$/, // 只检测以.sass结尾的文件,
use: getStyleLoader('stylus-loader'),
},
{
test: /.(png|jpe?g|svg| gif| webg)$/, // 图片格式
type: 'asset',
parser: {
dataUrlCondition: {
// 小于10kb 的转base64
maxSize: 10 * 1024
}
},
generator: {
filename: "imgs/[hash:8][ext][query]",
}
},
{
test: /.(ttf|woff2 |woff | mp3 | mp4)$/, // 图标字体格式
type: 'asset/resource',
generator: {
filename: "fonts/[hash:8][ext][query]",
}
},
{
test: /.m?js$/,
exclude: /(node_modules|bower_components)/, // 排除的文件名称
use: {
loader: 'babel-loader',
// options: {
// presets: ['@babel/preset-env']
// }
}
}
]
},
// 插件
plugins: [
new ESLintPlugin({
context: path.resolve(__dirname, '../src'),
}),
new HtmlWebpackPlugin({
// 模板,以pubilc/index.html为模板创建新的文件
// 新的html文件特点;1.结构和原来一致2.自动引入打包的js文件
template: path.join(__dirname, '../pubilc/index.html')
}),
new MiniCssExtractPlugin({
filename: 'css/index.css',
})
],
// 生产模式不需要
// // 开发服务器: 不会输出任何资源,在内存中编译打包的
// devServer:{
// host: 'localhost', // 域名
// port: '3000', //端口
// open: true, // 是否自动打开浏览器
// },
// 模式
mode: 'production', // 生产模式
}
css压缩
-
下载插件
npm install css-minimizer-webpack-plugin --save-dev。参考 -
在webpack中配置
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); 在plugins中注册 plugins: [ new CssMinimizerPlugin() ],
html压缩
默认生产环境已经开启了html和js压缩,不需要做额外的配置。
webpack高级
webpack高级其实就是进行优化,提升开发体验,提升打包速度,减少代码体积,优化代码运行性能
提升开发体验
有时候开发环境出现报错,控制台输出的文件都是打包之后的报错位置,非常不友好,可以使用sourceMap解决。
sourceMap(源代码映射):是一个用来生成源代码与构建代码映射的方案。它会生成一个xxx.map文件,里面包含源代码和构建后每行/每列的映射关系。当构建后代码出现错误,可以通过该文件快速定位错误位置。
使用 参考
-
开发模式
cheap-module-source-map。-
优点:打包编译速度快,只包含行映射
-
缺点:没有列映射
devtool: 'cheap-module-source-map' //mode同级添加
-
-
生产模式
source-map-
优点:包含行/列映射
-
缺点:打包编译速度更慢
devtool: 'source-map'
-
-
注意:需要重启看效果
提升构建打包速度
模块热替换(HMR - hot module replacement)功能会在应用程序运行过程中,替换、添加或删除 模块,而无需重新加载整个页面。主要是通过以下几种方式,来显著加快开发速度:
- 保留在完全重新加载页面期间丢失的应用程序状态。
- 只更新变更内容,以节省宝贵的开发时间。
- 在源代码中 CSS/JS 产生修改时,会立刻在浏览器中进行更新,这几乎相当于在浏览器 devtools 直接更改样式。
- 该配置为默认配置
HMR使用 参考
- webpack基本配置
devServer:{
host: 'localhost', // 域名
port: '3000', //端口
open: true, // 是否自动打开浏览器
hot: true // 开启HML
},
-
注意
-
css样式默认有热加载,js没有。
-
也可以使用vue-loader和react-hot-loader来实现
-
Oneof使用
打包时每个文件都会经过所有的loader处理,虽然test正则没有匹配上,但是还是会经过,导致比较慢。开发和生产环境都可以配置
主要配置(开发环境为例):
rules: [
{
// 每个文件只能被其中一个loader处理,不会全部都经过一遍
oneOf: [
// loader配置
{
test: /.css$/, // 只检测以.css结尾的文件,
use: [
'style-loader',
'css-loader', // 将css资源编译成commonjs的模块到js中
], // 从下往上解析
},
{
test: /.less$/, // 只检测以.less结尾的文件,
use: [
'style-loader',
'css-loader',
'less-loader'
],
},
{
test: /.s[ac]ss$/, // 只检测以.sass结尾的文件,
use: [
'style-loader',
'css-loader',
'less-loader',
'sass-loader'
],
},
{
test: /.styl$/, // 只检测以.sass结尾的文件,
use: [
'style-loader',
'css-loader',
'less-loader',
'sass-loader',
'stylus-loader'
],
},
{
test: /.(png|jpe?g|svg| gif| webg)$/, // 图片格式
type: 'asset',
parser: {
dataUrlCondition: {
// 小于10kb 的转base64
maxSize: 10 * 1024
}
},
generator: {
filename: "imgs/[hash:8][ext][query]",
}
},
{
test: /.(ttf|woff2? | mp3 | mp4)$/, // 图片格式
type: 'asset/resource',
generator: {
filename: "fonts/[hash:8][ext][query]",
}
},
{
test: /.m?js$/,
exclude: /(node_modules|bower_components)/, // 排除的文件名称
use: {
loader: 'babel-loader',
// options: {
// presets: ['@babel/preset-env']
// }
}
}
]
}
]
include/exclude
在处理js文件要排除node_modules文件。开发和生产环境都可以做。注意只能同时用一种,不然就会报错。
- webpack配置
{
test: /.js$/,
// exclude: /(node_modules|bower_components)/, // 排除node_modules的文件名称
include:path.resolve(__dirname, "../src"), // 只处理src下面的文件
use: {
}
}
plugins: [
new ESLintPlugin({
context: path.resolve(__dirname, '../src'),
exclude: 'node_modules' // 默认值
}),
]
Cache
对eslint和babel编译结果进行缓存
-
webpack配置
{ test: /.js$/, // exclude: /(node_modules|bower_components)/, // 排除node_modules的文件名称 include:path.resolve(__dirname, "../src"), // 只处理src下面的文件 use: { loader: 'babel-loader', options: { cacheDirectory: true ,// 开启bable缓存 cacheCompression: false //关闭缓存文件压缩 } } }, plugins: [ new ESLintPlugin({ context: path.resolve(__dirname, '../src'), exclude: 'node_modules', // 默认值 cache: true, // 开启eslint缓存 cacheLocation: path.resolve(__dirname, '../node_modules/.cache/eslintCache') // 缓存路径 }), ] -
如果缓存成功就可以在node_modules下面看到一个.cache的文件
Thead
多线程提升js文件打包速度,也就是开启多喝线程同时干一件事情。每个进程开启时间大概为600ms,所以该方法比较适用于比较大的项目。开发和生产环境都可以配置。
-
获取cpu核数
-
下载包
npm i thread-loader -D -
webpack配置
const os =require('os'); const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); const threads =os.cpus().length // cpu核数 { test: /.?js$/, // exclude: /(node_modules|bower_components)/, // 排除node_modules的文件名称 include:path.resolve(__dirname, "../src"), // 只处理src下面的文件 use: [ { loader: 'thead-loader', // 在前面进行处理 }, { loader: 'babel-loader', options: { cacheDirectory: true ,// 开启bable缓存 cacheCompression: false //关闭缓存文件压缩 // presets: ['@babel/preset-env'] } } ] } // 插件 plugins: [ new TerserWebpackPlugin({ parallel:threads // 开启多进程和设置进程数量 }) ],
减少代码体积
Tree Shaking
开发的时候需要用到第三方库,有时候我们只会用到其中几个,所以将整个打包下来会导致体积很大。Tree Shaking用于移除js中没有用的代码。注意:它依赖es module。默认已经开启不需要做任何配置。
Babel
babel为编译的每一个文件都加入了辅助代码,使得体积过大。
babel对一些公共方法使用非常小的辅助代码,比如_extend。默认情况下会被添加到每一个需要他的文件中,我们可以将这些辅助代码作为一个独立模块,来避免重复使用。
-
下载包
npm i @babel/plugin-transform-runtime -D-
可以禁用babel对每个文件runtime注入,并可以使所有辅助代码从这里引用
-
开发和生产环境都可以配置
-
webpack配置
{ loader: 'babel-loader', options: { cacheDirectory: true ,// 开启bable缓存 cacheCompression: false, //关闭缓存文件压缩 plugins: ['@babel/plugin-transform-runtime'] // 在babel使用 } }
-
image Minimizer
进行图片压缩,减少图片体积。只有本地图片才需要进行压缩。参考
-
下载包
npm install image-minimizer-webpack-plugin imagemin --save-dev- 无损压缩
npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo --save-dev - 有损压缩
npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo --save-dev
- 无损压缩
-
webpack配置,以无损压缩为例
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin"); // 所有有关压缩都在此配置 optimizations:{ // 压缩配置 minimizer:[ // 压缩图片 new ImageMinimizerPlugin({ minimizer: { implementation: ImageMinimizerPlugin.imageminGenerate, options: { plugins: [ ["gifsicle", { interlaced: true }], ["jpegtran", { progressive: true }], ["optipng", { optimizationLevel: 5 }], [ "svgo", { plugins: [ 'preset-default', 'prefixIds', { name: "sortAttrs", params: { xmlnsOrder: 'alphabetical' } } ], }, ], ], }, } }), ] },
优化代码运行性能
code spilt
打包代码时会将所有的js文件打包到一个文件中,体积太大,如果我们只要渲染首页,就应该只加载首页对应的js文件。所以我们需要将打包生成的文件进行代码分割,生成多个文件,渲染那个页面就只加载那个js文件。
代码分割(code spilt) 参考
- 分割文件,将打包生成的文件进行分割,生成多个js文件
- 按需加载,需要哪个文件就加载那个文件
webpack配置多入口。使用 entry 配置手动地分离代码
entry: {
index: './src/index.js',
main: './src/main.js',
},
output: {
filename: '[name].bundle.js', // [name]为webpack命名方式,文件名自己命名
path: path.resolve(__dirname, 'dist'),
},
公共代码单独打包成js,进行复用
optimization: {
// 代码分割配置
splitChunks: {
chunks: "all", // 对所有模块都进行分割
// 以下是默认值
// minSize: 20000, // 分割代码最小的大小
// minRemainingSize: 0, // 类似于minSize,最后确保提取的文件大小不能为0
// minChunks: 1, // 至少被引用的次数,满足条件才会代码分割
// maxAsyncRequests: 30, // 按需加载时并行加载的文件的最大数量
// maxInitialRequests: 30, // 入口js文件最大并行请求数量
// enforceSizeThreshold: 50000, // 超过50kb一定会单独打包(此时会忽略minRemainingSize、maxAsyncRequests、maxInitialRequests)
// cacheGroups: { // 组,哪些模块要打包到一个组
// defaultVendors: { // 组名
// test: /[\/]node_modules[\/]/, // 需要打包到一起的模块
// priority: -10, // 权重(越大越高)
// reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
// },
// default: { // 其他没有写的配置会使用上面的默认值
// minChunks: 2, // 这里的minChunks权重更大
// priority: -20,
// reuseExistingChunk: true,
// },
// },
// 修改配置
cacheGroups: {
// 组,哪些模块要打包到一个组
// defaultVendors: { // 组名
// test: /[\/]node_modules[\/]/, // 需要打包到一起的模块
// priority: -10, // 权重(越大越高)
// reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
// },
default: {
// 其他没有写的配置会使用上面的默认值
minSize: 0, // 我们定义的文件体积太小了,所以要改打包的最小文件体积
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
按需加载,动态导入
第一种,也是推荐选择的方式是,使用符合 ECMAScript 提案 的 import() 语法 来实现动态导入。
第二种,则是 webpack 的遗留功能,使用 webpack 特定的 require.ensure。
写法,使用import动态引入js文件,改文件就会单独打包为一个js文件
import('./js/count').then((res) =>{
console.log('count', '‘成功');
},() =>{
console.log('count', '失败');
});
单入口。其他都用默认值即可
optimization: {
// 代码分割配置
splitChunks: {
chunks: "all", // 对所有模块都进行分
}
}
动态导入文件命名
// 动态引入
import(/*webpackChunKName: 'math'*/ './js/sum').then(({sum}) => {
console.log('sum', sum(1,2));
},() =>{
console.log('sum', '失败');
})
output: {
// 输出路径。绝对路径
path: path.resolve(__dirname, '../dist'), // __dirname代表当前文件的目录
// js文件打包路径
filename: 'static/js/main.js',
chunkFilename: 'static/js/[name].js', // 指定动态导入文件的路径名称,[name]会对应上面的math
// 自动清空上次打包结果
clean: true,
},
统一命名配置
output: {
// 输出路径。绝对路径
path: path.resolve(__dirname, '../dist'), // __dirname代表当前文件的目录
// js文件打包路径
filename: 'static/js/[name].js',
chunkFilename: 'static/js/[name].chunk.js',
// 图片字体等统一处理文件名称
assetModuleFilename: "static/media/[hash:8][ext][query]",
// 自动清空上次打包结果
clean: true,
},
// 做了以上assetModuleFilename配置generator就可以不需要
{
test: /.(ttf|woff2 |woff | mp3 | mp4)$/, // 图标字体格式
type: 'asset/resource',
// generator: {
// filename: "fonts/[hash:8][ext][query]",
// }
},
new MiniCssExtractPlugin({
filename: 'css/[name].css',
chunkFilename: 'css/[name].chunk.css',
})
...
Preload/Prefetch
如果用户点击时加载的资源太大,会导致卡顿效果。所以可以当浏览器空闲的时候加载后续的资源。
Preload: 告诉浏览器立即加载资源
Prefetch:空闲才加载资源
共同点:
- 都会加载资源并不执行
- 都有缓存
区别:
Preload优先级比较高,Prefetch优先级比较低Preload只加载当前页面需要使用的资源,Prefetch可以加载当前页面资源,也可以加载下一个页面需要的资源。
总结:
- 当页面优先级比较高的时候用
Preload - 下一个页面需要使用资源用
Prefetch
问题:
- 兼容性比较差。参考
Preload兼容性比Prefetch好
下载包 npm install --save-dev @vue/preload-webpack-plugin 。 参考
webpack配置
const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin');
new PreloadWebpackPlugin({
rel: 'preload',
as: 'script'
})
// 如果rel为Prefetch as属性就不需要。打包后实际为link标签。
network cache
当一个文件B发生变化,但是又不想用了B文件的A文件发生变化,可以在两者中间加一个runtime.js文件来解决。
-
new MiniCssExtractPlugin({ filename: 'css/[name].[contenthash:10].css', // [contenthash:10] chunkFilename: 'css/[name].chunk.[contenthash:10].css', }), -
optimization: { // 生成runtime文件 runtimeChunk: { name: (enwtrypoint) =>{ `runtimes: ${enwtrypoint}.js` } } },
core.js
可以解决js代码在低版本浏览器不兼容问题
core.js是专门用来做es6以及以上api的polyfill
polyfill翻译过来就是补丁。
-
下载:
npm i core-js -
在main.js手动全部引入
import "core-js"; -
在main.js按需加载
import "core-js/es/promise"; -
在babel-config.js配置自动引入
// bable 配置文件 module.exports = { // 智能映射,能够编译es6语法 presets: [ [ '@babel/preset-env', { useBuiltIns: 'usage', // 按需自动加载core corejs: 3 // 版本 } ] ], }
PWA
渐进式网络应用程序:是一种可以提供类似于native app体验的web app技术,重要的是在离线时也可以持续运行,内部通过service
Workers技术实现
-
下载包npm install workbox-webpack-plugin --save-dev参考
-
webpack配置
const WorkboxPlugin = require('workbox-webpack-plugin'); new WorkboxPlugin.GenerateSW({ // 这些选项帮助快速启用 ServiceWorkers // 不允许遗留任何“旧的” ServiceWorkers clientsClaim: true, skipWaiting: true, }), -
main引入
if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/service-worker.js').then(registration => { console.log('SW registered: ', registration); }).catch(registrationError => { console.log('SW registration failed: ', registrationError); }); }); }
注:如有错误欢迎指正,一起学习!!!