1 webpack初体验
1.1准备工作
1.初始化包描述文件
npm init
2.全局安装webpack
npm i webpack-cli -g
3.将webpack添加到package.json的依赖中
npm i webpack-cli -D
1.2运行指令
运行不了的话前面加npx
开发环境:
webpack ./src/index.js -o ./build/built.js --mode=development
(webpack会以./src/index.js -o作为入口文件进行打包,打包后输出到./build/build.js中 整体打包环境是开发环境)
生产环境:
webpack ./src/index.js -o ./build/built.js --mode=production
(webpack会以./src/index.js -o作为入口文件进行打包,打包后输出到./build/build.js中 整体打包环境是生产环境)
1.3webpack打包资源分类
可以打包JS,JSON
不可以打包CSS,图片
1.4生产环境和开发环境的异同
- 生产环境比开发环境多一个压缩js代码,其他区别不大
- 生产环境和开发环境将es6的模块编译成浏览器可以识别的模块
2 webpack打包样式资源
2.1webpack.config.js
- 在根目录下 这是webpack配置文件
- 作用是指示webpack干哪些活(运行webpack指令的时候会加载里面的配置)
- 写配置要用commpn.js语法 因为所有的构建工具是基于node.js的
// 配置文件
//resolve用来拼接绝对路径的方法
const {resolve} = require('path')
module.exports={
//webpack配置
//入口
entry:'./src/index.js',
//输出
output:{
//输出文件名
filename:'built.js',
//输出路径 通常输出绝对路径 通常会引入nodejs的path模块
//__dirname是nodejs的变量 代表当前文件的目录绝对路径
path:resolve(__dirname,'build')
},
//loader配置
//不同的文件需要配置不同的loader
module:{
rules:[
{
//详细的loader配置
//test代表匹配哪些文件 通常是正则表达式的形式
test: /\.css$/, //匹配css文件
//use 使用哪些loader
//从下向上执行
use:[
'style-loader',//创建style标签 将js中的css样式资源插入 添加到页面中生效
'css-loader'//将css文件以字符串的形式变成commonjs的模块加载到js中 里面的内容是样式字符串
]
},
{
test:/\.less$/,
use:[
'style-loader',
'css-loader',
'less-loader',//将less文件编译成css文件
]
}
]
},
//plugins插件
plugins:[],
//mode 模式
mode:'development'
}
下载loader
npm i css-loader style-loader -D
npm i less -D
npm i less-loader -D
运行
npm run build
3 webpack打包html资源
/*
loader:1.下载 2.使用(配置loader)
plugins:1.下载 2.引入 3.使用(配置plugins)
*/
const {resolve} = require('path')
//引入plugins插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports={
entry:'./src/index.js',
output:{
filename:'built.js',
path: resolve(__dirname,'build')
},
//loader配置
module:{
rules:[]
},
//plugins配置
plugins:[
//使用plugins
//功能 默认串接一个空的html文件 自动引入打包输出的所有资源(js、css)
//而我们的需求 需要一个有结构的html文件
new HtmlWebpackPlugin({
//所以要复制'./src/index.html'文件 并自动引入打包输出的所有资源
template:'./src/index.html'
})
],
mode:'development'
}
下载plugins
npm i html-webpack-plugin -D
4 webpack打包图片资源
/*
loader:1.下载 2.使用(配置loader)
plugins:1.下载 2.引入 3.使用(配置plugins)
*/
const {resolve} = require('path')
//引入plugins插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports={
entry:'./src/index.js',
output:{
filename:'built.js',
path: resolve(__dirname,'build')
},
module:{
rules:[
{
test:/\.css$/,
//使用多个loader用use
use:[
'style-loader',
'css-loader'
]
},
{
//处理图片资源
//z这种处理方式处理不了html中的图片
test:/.(jpg|png|gif)$/,
//使用一个loader用loader
loader:'url-loader',
//loader的配置可以使用options
options:{
limit:8*1024, //当发现图片大小小于8kb就会被base64编码处理 优点:减轻服务器压力,缺点:图片体积变大(文件请求速度变慢)
esModule:false,
name:'[hash:10].[ext]'//对图片进行重命名 [hash:10]:取hash值的前10位;.[ext]:文件的原扩展名
}
},
// 使webpack能处理html中包含的图片
{
test:/\.html$/,
loader:'html-loader',//用于处理html文件中的img图片 负责引入图片 使图片能被url-loader处理
// 这样操作会出现问题:因为url-loader默认使用es6进行解析,而html-loader引入图片是commonjs
// 解析的时候会出现问题[object Module]
// 解决:关闭url-loader的es6Module,esModule:false 使用commonjs解析
// esModule:false
options:{
esModule:false
}
}
]
},
plugins:[
//使用plugins
new HtmlWebpackPlugin({
template:'./src/index.html'
})
],
mode:'development'
}
下载url-loader、file-loader
npm i url-loader file-loader html-loader -D
目前webpack5已经可以解析图片样式,所以可以不用配置了
6 webpack打包其他资源
什么是其他资源:字体、图标等 (无需做任何处理而直接被输出)
/*
loader:1.下载 2.使用(配置loader)
plugins:1.下载 2.引入 3.使用(配置plugins)
*/
const {resolve} = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports={
entry:'./src/index.js',
output:{
filename:'built.js',
path: resolve(__dirname,'build')
},
module:{
rules:[
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
},
//打包其他资源(除html js css)
{
exclude:/\.(css|js|html)$/,//排除css js css
loader:'file-loader'
}
]
},
plugins:[
new HtmlWebpackPlugin({
template:'./src/index.html'
})
],
mode:'development'
}
目前webpack5已经可以解析图标样式,所以可以不用配置了
7 webapck-devServer
问题:打包完成后再次修改内容需要重新打包
解决:使用devServer 自动打包 开发者仅需要写源代码
下载包:npm i webpack-dev-server -D
配置1
const {resolve} = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports={
entry:'./src/index.js',
output:{
filename:'built.js',
path: resolve(__dirname,'build')
},
module:{
rules:[]
},
plugins:[],
mode:'development',
//开发服务器 devServer--用于自动化(自动编译、自动打开浏览器、自动刷新浏览器。。。。)
//devServer的特点:没有输出,只会在内存编译中进行打包
//启动devServer指令:npx webpack-dev-server
//下载包:npm i webpack-dev-server -D
devServer:{
// contentBase:resolve(__dirname,'build'),
compress:true,//启用gzip压缩
port:3000,//指定开发服务器的端口号
// contentBase: "./public",
static:resolve(__dirname,'build'),
open:true//自动打开浏览器
}
}
package.json里面修改
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"dev":"webpack-dev-server"
},
运行
npm run build
npm run dev
8 webpack环境介绍
mode模式 | 描述 | 功能描述 |
---|---|---|
development | 开发环境:能让代码在本地调试运行的环境 | 源代码–>webpack–>bundle |
production | 生产环境:能让代码优化上线的运行环境 | 1.将融合在js中的css取出 2.压缩代码 3.代码兼容性处理 |
9 webpack 生产环境 提取css文件
(1)下载相关依赖
npm i mini-css-extract-plugin -D
(2)webpack.config.js配置
// 配置文件
//resolve用来拼接绝对路径的方法
const {resolve} = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports={
entry:'./src/js/index.js',
output:{
filename:'js/built.js',
path:resolve(__dirname,'build')
},
module:{
rules:[
{
test: /\.css$/,
use:[
// 'style-loader',//创建style标签将样式放入
MiniCssExtractPlugin.loader,//取代style-loader 作用:将js中的css提取为单独文件
'css-loader'//将css文件整合到js中
]
},
]
},
plugins:[
new HtmlWebpackPlugin({
template:'./src/index.html'
}),
new MiniCssExtractPlugin({
filename:'css/built.css'//规定打包后css文件的路径
})
],
mode:'development'
}
10webpack 生产环境 css兼容性处理
(1)安装相关依赖
npm i postcss-loader postcss-preset-env -D
(2)package.json配置
添加
"browserslist":{
"development":[
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"production":[
">0.2%",
"not dead",
"not op_mini all"
]
}
(3)webpack.config.js配置
// 配置文件
//resolve用来拼接绝对路径的方法
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
//设置nodejs环境变量
process.env.NODE_ENV = 'development'
module.exports = {
entry: "./src/js/index.js",
output: {
filename: "js/built.js",
path: resolve(__dirname, "build"),
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
/*
css兼容性处理:需要postcss库---->postcss-loader
还需要插件 npm i postcss-loader postcss-preset-env -Dpostcss-preset-env
帮助postcss找到package.json中的browserslist里面的配置 通过配置加载指定的css兼容性样式
*/
//配置有两种写法
//第一种:使用loader的默认配置
//'postcss-loader'
//第二种 修改默认配置
/*
还在package.json中配置
"browserslist":{
//开发环境:如果需要改为开发环境-->设置node环境变量:process.env.NODE_ENV = development
"development":[
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
//生产环境:默认是生产环境
"production":[
">0.2%",
"not dead",
"not op_mini all"
]
}
*/
{
loader: "postcss-loader",
options: {
postcssOptions:{
ident: "postcss",
plugins:['postcss-preset-env']
}
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
new MiniCssExtractPlugin({
filename: "css/built.css",
}),
],
mode: "development",
};
11 webpack 生产环境 压缩css
(1)下载相关依赖
npm i optimize-css-assets-webpack-plugin -D
(2)webpack相关配置
// 配置文件
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
//引入用于压缩的插件
const optimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin")
process.env.NODE_ENV = 'development'
module.exports = {
entry: "./src/js/index.js",
output: {
filename: "js/built.js",
path: resolve(__dirname, "build"),
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions:{
ident: "postcss",
plugins:['postcss-preset-env']
}
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
new MiniCssExtractPlugin({
filename: "css/built.css",
}),
//调用用于压缩的插件
//只要用new调用之后他就可以压缩css了
new optimizeCssAssetsWebpackPlugin()
],
mode: "development",
};
12 webpack生产环境 js语法检查 eslint
(1)下载相关包
npm i eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import -D
(2)配置package.json
添加
"eslintConfig": {
"extends": "airbnb-base"
}
(3)webpack配置
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
/* 语法检查
注意:只检查用户自己写的源代码,第三方的库是不用检查的
设置检查规则:在package.json中的eslintConfig中设置 推荐使用airbnb规则
需要下载三个库:eslint-loader eslint-config-airbnb-base eslint eslint-plugin-import
//在package.json中配置
"eslintConfig": {
"extends": "airbnb-base"
}
*/
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
fix: true,
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
mode: 'development',
};
13 webpack 生产环境js的兼容性处理
出现问题:ie浏览器不兼容
解决:使用babel-loader进行js兼容性处理
作用:将es6语法转化为es5及以下的语法
下载依赖包:npm i babel-loader @babel/preset-env @babel/core -D
{
test: /\.js$/,
//不能监测node_modules中的东西
exclude: /node_modules/,
loader: "babel-loader",
options: {
//预设 指示babel做怎么样的兼容性处理
presets: [
[
"@babel/preset-env",
{
//按需加载
useBuiltIns: "usage",
// 指定core-js版本
corejs: { version: 3 },
targets: {
chrome: "60",
firefox: "50",
},
},
],
],
},
},
14 webpack 生产环境 压缩js、html代码
(1)js压缩
只需要设置 mode:production
因为在生产环境下默认压缩js代码
(2)html压缩
对html插件进行配置
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
minify:{
collapseWhitespace:true,//移除空格
removeComments:true//移除注释
}
}),
],
(3)总结
/* eslint-disable linebreak-style */
// 配置文件
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
minify:{
collapseWhitespace:true,//移除空格
removeComments:true//移除注释
}
}),
],
// 生产环境自动压缩js代码
mode: 'production',
};
附件1:生产环境基本配置
const { resolve } = require("path");
//提取css文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
//压缩css
const optimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
//处理html资源
const HtmlWebpackPlugin = require("html-webpack-plugin");
process.env.NODE_ENV = "development";
// 复用loader
const commonCssLoader = [
MiniCssExtractPlugin.loader,
"css-loader",
// css兼容性处理 顺序不能变
{
loader: "postcss-loader",
options: {
postcssOptions: {
ident: "postcss",
plugins: ["postcss-preset-env"],
},
},
},
];
module.exports = {
entry: "./src/js/index.js",
output: {
filename: "js/built.js",
path: resolve(__dirname, "build"),
},
module: {
rules: [
//处理css样式
{
test: /\.css$/,
use: [...commonCssLoader],
},
//处理less样式
{
test: /\.less$/,
use: [...commonCssLoader, "less-loader"],
},
//正常来讲一个文件只能被一个loader处理,当一个文件要被多个loader处理时
//就一定要指定loader的执行顺序 先执行eslint-loader 再bable-loader
//js格式处理
{
test: /\.js$/,
exclude: /node_modules/,
enfore: "pre",
loader: "eslint-loader",
options: {
fix: true,
},
},
//js兼容性处理
{
test: /\.js$/,
exclude: /node_modules/,
loader: "bable-loader",
options: {
presets: [
[
"@bable/preset-env",
{
useBuiltIns: "useage",
corejs: { version: 3 },
targets: {
chrome: "60",
firefox: "50",
},
},
],
],
},
},
//处理图片资源
{
test: /\.(jpg|png|gif)$/,
loader: "url-loader",
options: {
limit: 8 * 1024,
name: "[hash:10].[ext]",
outputPath: "imgs",
esModule: false,
},
},
//处理html中的图片资源
{
test: /\.html$/,
loader: "html-loader",
options: {
esModule: false,
},
},
//处理其他文件
{
exclude:/\.(js|html|css|less|jpg|png|gif)$/,
loader:'file-loader',
options:{
outputPath:'media'
}
}
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/built.css",
}),
new optimizeCssAssetsWebpackPlugin(),
new HtmlWebpackPlugin({
template: "./src/index.html",
minify:{
collapseWhitespace:true,
removeComments:true
}
}),
],
mode: "production",
};
14 webpack 性能优化介绍
分类 | 要做什么? |
---|---|
开发环境性能优化(开发环境的目标:代码运行即可) | 1. 优化webpack打包构建速度 2. 优化代码调试 |
生产环境性能优化(生产环境目标:代码上线运行即可,无需调试) | 1. 优化webpack打包构建速度 2. 优化代码运行的性能 |
15 开发环境性能优化-优化打包构建速度-HMR
(1)之前生产环境的问题:
部分文件更改后重新打包时,没有被更改的部分也参与打包。
(2)解决方法:开启HMR功能
const {resolve} = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports={
entry:'./src/js/index.js',
output:{
filename:'js/built.js',
path: resolve(__dirname,'build')
},
module:{
rules:[
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
},
{
test:/\.less$/,
use:[
'style-loader',
'css-loader',
'less-loader'
]
},
{
test:/.(jpg|png|gif)$/,
loader:'url-loader',
options:{
limit:8*1024,
esModule:false,
name:'[hash:10].[ext]',
outputPath:'imgs'
}
},
{
test:/\.html$/,
loader:'html-loader',
options:{
esModule:false
}
},
{
exclude:/\.(css|js|html|jpg|png|gif|less)$/,
loader:'file-loader',
options:{
name:'[hash:10].[ext]',
outputPath:'media'
}
}
]
},
plugins:[
new HtmlWebpackPlugin({
template:'./src/index.html'
})
],
mode:'development',
devServer:{
compress:true,
port:3000,
static:resolve(__dirname,'build'),
open:true,
//开启HMR功能
hot:true
}
}
(3)HMR功能
HMR:hot module replacement 热模块替换/模块热替换
作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块),可以极大程度的提高构建速度。
- 样式文件:可以直接使用HMR功能,因为style-loader内部实现了
- js文件:默认不使用HMR功能
—>注意:修改后的HMR功能仅适用于非入口文件的js文件,入口文件的改变依旧会改变其他文件
—>修改js代码添加支持HMR功能的代码 - 例如被修改的是print.js件,
console.log('print.js被重新加载了')
function print(){
const content='hello print'
console.log(content)
}
export default print;
- 实现HMR,修改index.js
import '../css/index.css'
import '../css/iconfont.css'
console.log("index.js被重新加载")
function add(a,b){
return a+b
}
0
console.log(add(1,2))
if(module.hot){
//module.hot==true说明开启了HMR功能
//此方法会监听./print.js文件的变化,一旦发生变化,其他模块不会重新打包构建 而是去执行后面的回调函数
module.hot.accept('./print.js',function(){
print();
})
}
- html文件:默认不能使用HMR功能,同时html文件不能热更新了 。
—>解决:修改entry入口,将html文件引入
—>说明:修改entry之后还是不能用HMR功能哦~
—>讨论:html文件是否需要HMR呢?不需要,因为html文件只有一个,当他发生变化的时候html文件是一定要变化。而不像js文件,可以有多个需要HMR控制一个文件变化其他js文件不重新打包。
entry:('./src/js/index.js','./src/index.html'),
16 开发环境性能优化-优化调试代码-source_map
(1)source_map是什么?
提供一种源代码到构建后代码的一个映射的技术(例如:构建后代码出错,可以通过映射关系来追踪到源代码的错误。)
格式: (inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map
- inline-source-map:内联,source_map文件代码在build,js文件中,只生成一个source_map文件,构建速度更快
- hidden-source-map:外部,source_map文件单独生成
- eval-source-map:内联,source_map文件代码在build,js,生成多个source_map文件,并且都在eval函数中
- nosources-source-map:外部,source_map文件单独生成
- cheap-source-map:外部,source_map文件单独生成
- cheap-module-source-map:外部,source_map文件单独生成
相比于cheap-source-map的区别在于 module会将loader的source-map也加入
配置 | sourcemap文件位置 | 描述 | |
---|---|---|---|
source-map | 外部 | source_map文件单独生成 | 提供准确的错误代码信息和源代码的错误位置精确的行和列 |
inline-source-map | 内联 | source_map文件代码在build,js文件中,只生成一个source_map文件,构建速度更快 | 提供准确的错误代码信息和源代码的错误位置精确的行和列 |
hidden-source-map | 外部 | source_map文件单独生成 | 提示错误代码的错误原因,但是没有错误位置,不可以追踪到源代码的错误,只能提示到构建后代码的错误位置 |
eval-source-map | 内联 | source_map文件代码在build,js,生成多个source_map文件,并且都在eval函数中 | 提供准确的错误代码信息和源代码的错误位置,并且代码位置会标注hash值 |
nosources-source-map | 外部 | source_map文件单独生成 | 提供准确的错误代码准确信息,但是没有任何源代码的错误信息。 |
cheap-source-map | 外部 | source_map文件单独生成 | 提供准确的错误代码行的信息(而不是准确的错误位置)和源代码的错误位置,精确到行 |
cheap-module-source-map | 外部 | ource_map文件单独生成相比于cheap-source-map的区别在于 module会将loader的source-map也加入 | 提供准确的错误代码行的信息(而不是准确的错误位置)和源代码的错误位置,精确到行 |
名称 | 描述 |
---|---|
外部 | 生成单独文件 |
内部 | 不生成单独文件,速度更快 |
(2)使用source_map
const {resolve} = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports={
entry:('./src/js/index.js','./src/index.html'),
output:{
filename:'js/built.js',
path: resolve(__dirname,'build')
},
module:{
rules:[
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
},
{
test:/\.less$/,
use:[
'style-loader',
'css-loader',
'less-loader'
]
},
{
test:/.(jpg|png|gif)$/,
loader:'url-loader',
options:{
limit:8*1024,
esModule:false,
name:'[hash:10].[ext]',
outputPath:'imgs'
}
},
{
test:/\.html$/,
loader:'html-loader',
options:{
esModule:false
}
},
{
exclude:/\.(css|js|html|jpg|png|gif|less)$/,
loader:'file-loader',
options:{
name:'[hash:10].[ext]',
outputPath:'media'
}
}
]
},
plugins:[
new HtmlWebpackPlugin({
template:'./src/index.html'
})
],
mode:'development',
devServer:{
compress:true,
port:3000,
static:resolve(__dirname,'build'),
open:true,
hot:true
},
//启用source_map
devtool:"source-map"
}
(3)source_map是如何映射错误的?
- devtool:“source-map”、 devtool:"inline-source-map"时时
提供准确的错误代码信息和源代码的错误位置
精确的行和列
- devtool:"hidden-source-map"时
提示错误代码的错误原因,但是没有错误位置,不可以追踪到源代码的错误,只能提示到构建后代码的错误位置
代码没有一万多行
-
devtool:"eval-source-map "时
提供准确的错误代码信息和源代码的错误位置,并且代码位置会标注hash值
-
devtool:"nosources-source-map "时
提供准确的错误代码准确信息,但是没有任何源代码的错误信息。 -
devtool:"cheap-module-source-map "时
提供准确的错误代码行的信息(而不是准确的错误位置)和源代码的错误位置
精确到行
(4)如何选择哪种模式
环境 | 要求 | 选择 |
---|---|---|
开发环境development | 速度快 | 1.速度(eval>inline>cheap>…)2.eval-cheap-souce-map>eval-source-map |
开发环境development | 调试友好 | source-map>cheap-module-source-map>cheap-source-map |
开发环境development | 速度快且调试友好 | eval-source-map(vue默认使用)、eval-cheap-module-source-map |
生产环境production | 代码隐藏 | nosources-source-map(全部隐藏)、hidden-source-map(隐藏源代码,会提示构建后代码错误) |
生产环境production | 调试友好 | source-map、cheap-module-source。注意:内联会让代码体积变大,所以在生产环境中不使用内联的方式 |
结论:
- 开发环境:eval-source-map
- 生产环境:source-map(无需隐藏的时候);hidden-source-map、nosources-source-map(需要隐藏的时候)
17生产环境优化-oneOf
为什么要用oneOf?
module的rules里面存在大量的loader,如果不做处理的话每个文件都会被所有的loader都过一遍。
使用:用oneof来包裹所有的loader
oneOf的意思就是:以下loader只会匹配一个,可以提升处理的性能
注意:使用oneOf后就不能存在两个配置处理同一种文件了
例如处理js的eslint-loader
和js兼容性处理的loader
解决方法:将eslint-loader提取出来,放在oneOf的外面
18 生产环境优化-缓存
作用:提升第二次打包的构建速度
分类 | 解决方式 |
---|---|
babel缓存 | cacheDirectory:true |
文件资源缓存 | 修改文件名(添加hsah值) |
(1)babel缓存
为什么要babel缓存? 在开发过程中js代码的量是比较多的,
(2)文件资源缓存
在根目录上创建server.js文件,进行服务器代码的编写
// 服务器代码
/*
启动服务器
方法1:
安装依赖:npm i nodemon -g
执行:nodemon server.js
方法2:
node server.js
访问服务器 http://localhost:3000
*/
const express = require('express')
const app = express();
app.use(express.static('build',{maxAge:1000*3600}));
app.listen(3000);
编写完成后就可以将文件资源放入缓存中,用户第二次访问时就会优先读取缓存
造成问题: 当文件内容变化时,用户由于文件缓存还没过期获取到的还是缓存中的内容
解决方法: 给打包文件添加hash值
推荐使用:contenthahs
19 开发环境优化 tree shaking
作用: 去除应用程序中没有使用的代码(js、css等),减少代码打包体积。
使用前提:
1.必须使用es6模块化
2.开启production环境满足这两个条件,自动的会实现tree shaking
sideEffects:fasle
作用: 在package中所有的代码都是没有副作用的代码,都可以进行tree shaking
会出现问题: css代码、其他文件被误认为没有使用的代码而被干掉
解决: sideEffects:[“*.css”]
20 优化-code-split
代码分割:可以实现js的按需加载功能
1.配置1:多入口配置
const { resolve } = require("path");
//处理html资源
const HtmlWebpackPlugin = require("html-webpack-plugin");
process.env.NODE_ENV = "production";
module.exports = {
//多入口:有一个入口,最终输出就有一个bundle
entry: {
main:"./src/js/index.js",
test:"./src/js/test.js"
},
output: {
// [name].取文件名
filename: "js/[name].[contenthash:10].js",
path: resolve(__dirname, "build"),
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
],
mode: "production",
devtool:'source-map'
};
当文件数量过多的时候,不灵活。
2.配置2:optimization
optimization作用:
入口 | 说明 |
---|---|
单入口情况 | 将node_modules中文件单独打包 |
多入口情况 | 自动分析入口chunk中有没有公共文件,如果有单独打包为一个chunk |
注意:文件超过30kb才生效
3.配置3:使用js代码控制
22-优化-懒加载 预加载
1懒加载:
懒加载可以理解为延迟加载,即为触发了某些条件后的加载,而不是一上来就加载。
console.log('index.js文件被加载了')
// import {mul} from './test'
// document.getElementById('btn').οnclick=function(){
// console.log(mul(4,5))
// }
// 期望:点击按钮之后test.js文件才加载
document.getElementById('btn').onclick=function(){
// 懒加载
// /*webpackChunkName:'test'*/ :修改构建名称
import(/*webpackChunkName:'test'*/'./test').then(({mul})=>{
console.log(mul(4,5))
})
}
2.预加载
预加载:会在使用之前提前加载js文件,与正常加载的区别是等其他文件加载完毕,等浏览器空闲了在偷偷加载还没有使用的资源。
正常加载:可以认为是并行加载(同一时间加载多个文件)
注意:慎用 兼容性差
23-优化-PWA(一般不用)
PWA的作用:帮助我们的网页像app应用程序一样,可以实现离线访问,性能也可以更好。也称为渐进式网络开发应用程序。
·
因为兼容性问题:PWA的使用并不多
下载依赖;npm i workbox-webpack-plugin -D
1.配置webpack.config.js
2.在入口文件注册serviceworker
//注册serviceworker
//处理兼容性问题
if('serviceWorker' in navigator){
window.addEventListener('load',()=>{
navigator.serviceWorker.register('/service-worker.js')
.then(()=>{
console.log('serviceworke注册成功')
})
.catch(()=>{
console.log('serviceworke注册失败')
})
})
}
注意1:eslint不认识window、navigator全局变量
解决:需要修改package.json中eslintConfig配置
//支持浏览器中的全局变量
`“env”:{
“browser”:true
}`
注意2:service-worke代码必须运行在服务器上
解决方法1:使用nodejs
解决方法2:
全局安装serve: npm i serve -g
执行命令:serve -s build 启动服务器,将build目录下的所有资源作为静态资源暴露出去
24-优化-多进程打包
下载依赖的包:npm i thread-loader -D
开启多进程打包,进程启动大概为600ms,进程通信也会花时间,只有工作消耗时间较长的时候才需要
//js兼容性处理
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: "thread-loader",
options:{
workers:2//两个进程
}
},
{
loader: "babel-loader",
options: {
presets: [
[
"@babel/preset-env",
{
//按需加载
useBuiltIns: "usage",
// 指定core-js版本
corejs: { version: 3 },
targets: {
chrome: "60",
firefox: "50",
},
},
],
],
// 开启babel缓存
// 第二次构建的时候才会读取之前的缓存
cacheDirectory: true,
},
},
],
},
24-优化-externals
作用:防止将某些包打包到最终输出的依赖中。