初步体验webpack打包
webpack是一个静态资源打包工具。
它会以一个或多个文件作为打包的入口,将我们整个项目所有文件编译组合成一个或多个文件输出出去。
输出的文件就是编译好的文件,就可以在浏览器段运行了。
1.初始化最简单的一个目录文件,手动创建
main.js
import count from "./js/count";
import sum from "./js/sum";console.log(count(2,1));
console.log(sum(1,2,3,4));
index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h3>webpack</h3><!-- 这里直接运行报错 浏览器不识别ES6模块化 --><!-- <script src="../src/main.js"></script> --><!-- 运行的时候改成这个路径,webpack打包好的js文件 --><script src="../dist/main.js"></script>
</body>
</html>
2.下载依赖
npm init -y
初始化package.json文件 修改一下 main 的路径 ./src/main.js
{"name": "webpack_code","version": "1.0.0","description": "","main": "./src/main.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"keywords": [],"author": "","license": "ISC"
}
注意:package.json中name字段不能叫做webpack,否则下一步会报错
npm i webpack webpack-cli -D
3.启用webpack
开发模式
npx webpack ./src/main.js --mode=development
生产模式
npx webpack ./src/main.js --mode=production (生产环境会对代码压缩,文件非常小)
默认webpack会将文件打包输出到dist目录下,我们查看dist目录下文件情况就好了
npx webpack:是用来运行本地安装 webpack包的。
./src/main.js:指定webpack从main.js文件开始打包,不但会打包main.js,还会将其依赖也一起打包进来。
–mode=xxx:指定模式(环境)
webpack本身功能比较少,只能处理js资源,一旦遇到css等其他资源就会报错。
5大核心概念
1.entry(入口)
指示webpack从哪个文件开始打包
2.outpu(输出)
指示webpack打包完的文件输出到哪里去,如何命名等
3.loader(加载器)
webpack本身只能处理js、json等资源,其他资源需要借助loader,webpack才能解析
4.plugins(插件)
扩展webpack的功能
5.mode(模式)
主要由两种模式:
开发模式:development
生成模式:production
准备webpack配置文件
在项目 根目录 新建文件:webpack.config.js
const path=require('path');//nodejs核心模块,专门用来处理路径问题
module.exports={//入口entry:'./src/main.js', //相对路径//输出output:{//文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:path.resolve(__dirname,'dist'),//绝对路径//文件名filename:'main.js'},//加载器module:{rules:[//loader的配置]},//插件plugins:[//plugin的配置],//模式mode:'development',
}
运行打包:npx webpack
开发模式介绍
1.编译代码,使浏览器能识别运行
开发时我们有样式资源,字体图标,图片资源,html资源等,webpack默认都不能处理这些资源,所以我们要加载配置来编译这些资源
2.代码质量检查,树立代码规范
提前检查代码的一些隐患,让代码运行时能更加健壮。
提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。
官方文档
处理样式资源Css资源
(less,sass也是这样的处理步骤)
1,下载包
npm i css-loader style-loader -D
css-loader:负责将css文件编译成webpack能识别的模块
style-loader:会动态创建一个style标签,里面放置webpack中css模块内容
2. 创建一个css资源引入
main.js
import count from "./js/count";
import sum from "./js/sum";
//想要webpack打包资源,必须引入该资源
import './css/index.css'
console.log(count(2,1));
console.log(sum(1,2,3,4));
3.webpack.config.js 配置(如果有less,sass往rules里面添加即可)
处理图片资源 不需要下载和配置,如果想转换base64就需要配置一下
修改输出文件目录
处理字体图标资源
处理其他资源(比如视频,音频等等)
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
module.exports={//入口entry:'./src/main.js', //相对路径//输出output:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:path.resolve(__dirname,'dist'),//绝对路径//入口文件打包输出文件名filename:'static/js/main.js',//原理,在打包前,将path整个目录内容清空,再进行打包clean:true, //自动清空上次打包内容},//加载器module:{rules:[//loader的配置{test:/\.css$/i, //只检测.css结尾的文件use:[ //执行顺序,从右到左(从下到上)"style-loader", //将js中css通过创建style标签添加html文件中生效"css-loader" //将css资源编译成commonjs的模块到js中]},{test: /\.less$/i,use: [// 使用多个loader'style-loader','css-loader','less-loader', //将less编译成css文件],},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},generator:{//输出图片名称//[hash:10] hash值取前10位filename:"static/images/[hash:10][ext][query]"}},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",generator:{//输出名称filename:"static/media/[hash:10][ext][query]"}},{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行// options:{// presets:["@babel/preset-env"]// }}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"src"),}),new HtmlWebpackPlugin({//模板。以public/index.html文件创建新的html文件//新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源template:path.resolve(__dirname,"public/index.html")})],//开发服务器:不会输出资源,在内存中编译打包devServer:{host:'localhost',//启动服务器域名port:'3000',//启动服务器端口open:true,//是否自动打开浏览器},//模式mode:'development',
}
eslint使用
它是用来检测js和jsx语法的工具,可以配置各项功能
使用eslint,关键是写eslint配置文件,里面写上各种rules规则,将来运行eslint时就会以写的规则对代码进行检查
配置文件由很多种写法:
.eslintrc.*:新建文件,位于项目根目录
配置说明
1.下载包
npm i eslint-webpack-plugin eslint -D
vscode可以安装一个插件 ESLint
安装了这个插件就需要在配置一个文件 .eslintignore
忽略dist文件,里面的不检查
dist
2.定义.eslintrc.js 配置文件
module.exports={//继承Eslint规则extends:['eslint:recommended'],env:{node:true,//启用node中全局变量browser:true,//启用浏览器中全局变量},parserOptions:{ecmaVersion:6, //语法环境ES6sourceType:'module' //es module},rules:{"no-var":2 ,//不能使用var定义变量}
}
babel使用
主要用于将ES6语法编写的代码转换为向后兼容的JavaScript语法,以便能够运行在当前和旧版本的浏览器或其他环境中
1.下载
npm i babel-loader @babel/core @babel/preset-env -D
2.定义babel配置文件 babel.config.js
module.exports={//智能预设,能够编译ES6语法presets:["@babel/preset-env"]
}
处理html资源
1.下载
npm install --save-dev html-webpack-plugin
2.引入
const HtmlWebpackPlugin=require('html-webpack-plugin')
自动化
每次写完代码都需要手动输入指令才能编译代码,太麻烦,希望一切自动化
1.下载
npm i webpack-dev-server -D
2.配置 webpack.config.js
//开发服务器:不会输出资源,在内存中编译打包devServer:{host:'localhost',//启动服务器域名port:'3000',//启动服务器端口open:true,//是否自动打开浏览器},
3.运行
npx webpack serve
生产模式
生产模式是开发完成代码后,需要得到代码将来部署上线
主要对代码进行优化,让其运行性能更好。
1,优化代码运行性能
2,优化代码打包速度
准备两个配置文件来放不同的配置
webpack.dev.js 文件
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
module.exports={//入口entry:'./src/main.js', //相对路径//输出output:{//所有文件的输出路径//开发模式没有输出path:undefined,//入口文件打包输出文件名filename:'static/js/main.js',},//加载器module:{rules:[//loader的配置{test:/\.css$/i, //只检测.css结尾的文件use:[ //执行顺序,从右到左(从下到上)"style-loader", //将js中css通过创建style标签添加html文件中生效"css-loader" //将css资源编译成commonjs的模块到js中]},{test: /\.less$/i,use: [// 使用多个loader'style-loader','css-loader','less-loader', //将less编译成css文件],},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},generator:{//输出图片名称//[hash:10] hash值取前10位filename:"static/images/[hash:10][ext][query]"}},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",generator:{//输出名称filename:"static/media/[hash:10][ext][query]"}},{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行// options:{// presets:["@babel/preset-env"]// }}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),}),new HtmlWebpackPlugin({//模板。以public/index.html文件创建新的html文件//新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源template:path.resolve(__dirname,"../public/index.html")})],//开发服务器:不会输出资源,在内存中编译打包devServer:{host:'localhost',//启动服务器域名port:'3000',//启动服务器端口open:true,//是否自动打开浏览器},//模式mode:'development',
}
运行
npx webpack serve --config ./config/webpack.dev.js
webpack.prod.js 文件
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
module.exports={//入口entry:'./src/main.js', //相对路径//输出output:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:path.resolve(__dirname,'../dist'),//绝对路径//入口文件打包输出文件名filename:'static/js/main.js',//原理,在打包前,将path整个目录内容清空,再进行打包clean:true, //自动清空上次打包内容},//加载器module:{rules:[//loader的配置{test:/\.css$/i, //只检测.css结尾的文件use:[ //执行顺序,从右到左(从下到上)"style-loader", //将js中css通过创建style标签添加html文件中生效"css-loader" //将css资源编译成commonjs的模块到js中]},{test: /\.less$/i,use: [// 使用多个loader'style-loader','css-loader','less-loader', //将less编译成css文件],},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},generator:{//输出图片名称//[hash:10] hash值取前10位filename:"static/images/[hash:10][ext][query]"}},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",generator:{//输出名称filename:"static/media/[hash:10][ext][query]"}},{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行// options:{// presets:["@babel/preset-env"]// }}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),}),new HtmlWebpackPlugin({//模板。以public/index.html文件创建新的html文件//新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源template:path.resolve(__dirname,"../public/index.html")})],//模式mode:'production',
}
打包
npx webpack --config ./config/webpack.prod.js
简化运行代码的长度 配置 package.json
"scripts": {"start":"npm run dev","dev": "webpack serve --config ./config/webpack.dev.js","build":"webpack --config ./config/webpack.prod.js"},
提取css成单独文件
css文件目前被打包到js文件中,当js文件加载时,会创建一个style标签来生成样式
这样对于网站来说,会出现闪屏现象,用户体验不好
应该是单独的css文件,通过link标签加载性能才好
1.下载
npm i mini-css-extract-plugin -D
2.配置webpack.prod.js文件
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
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:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:path.resolve(__dirname,'../dist'),//绝对路径//入口文件打包输出文件名filename:'static/js/main.js',//原理,在打包前,将path整个目录内容清空,再进行打包clean:true, //自动清空上次打包内容},//加载器module:{rules:[//loader的配置{test:/\.css$/i, //只检测.css结尾的文件use:[ //执行顺序,从右到左(从下到上)MiniCssExtractPlugin.loader, //提取css成单独文件"css-loader" //将css资源编译成commonjs的模块到js中]},{test: /\.less$/i,use: [// 使用多个loaderMiniCssExtractPlugin.loader, //提取css成单独文件'css-loader','less-loader', //将less编译成css文件],},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},generator:{//输出图片名称//[hash:10] hash值取前10位filename:"static/images/[hash:10][ext][query]"}},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",generator:{//输出名称filename:"static/media/[hash:10][ext][query]"}},{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行// options:{// presets:["@babel/preset-env"]// }}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),}),new HtmlWebpackPlugin({//模板。以public/index.html文件创建新的html文件//新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源template:path.resolve(__dirname,"../public/index.html")}),new MiniCssExtractPlugin({filename:'static/css/main.css'})],//模式mode:'production',
}
Css兼容性处理
1.下载包
npm i postcss-loader postcss postcss-preset-env -D
2.配置webpack.prod.js文件
在css-loader后面 在less-loader前面 加代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
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:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:path.resolve(__dirname,'../dist'),//绝对路径//入口文件打包输出文件名filename:'static/js/main.js',//原理,在打包前,将path整个目录内容清空,再进行打包clean:true, //自动清空上次打包内容},//加载器module:{rules:[//loader的配置{test:/\.css$/i, //只检测.css结尾的文件use:[ //执行顺序,从右到左(从下到上)MiniCssExtractPlugin.loader, //提取css成单独文件"css-loader", //将css资源编译成commonjs的模块到js中{loader:"postcss-loader",options:{ //配置项postcssOptions:{plugins:["postcss-preset-env",//能解决大多数兼容性问题]}}},]},{test: /\.less$/i,use: [// 使用多个loaderMiniCssExtractPlugin.loader, //提取css成单独文件'css-loader',{loader:"postcss-loader",options:{ //配置项postcssOptions:{plugins:["postcss-preset-env",//能解决大多数兼容性问题]}}},'less-loader', //将less编译成css文件],},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},generator:{//输出图片名称//[hash:10] hash值取前10位filename:"static/images/[hash:10][ext][query]"}},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",generator:{//输出名称filename:"static/media/[hash:10][ext][query]"}},{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行// options:{// presets:["@babel/preset-env"]// }}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),}),new HtmlWebpackPlugin({//模板。以public/index.html文件创建新的html文件//新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源template:path.resolve(__dirname,"../public/index.html")}),new MiniCssExtractPlugin({filename:'static/css/main.css'})],//模式mode:'production',
}
package.json 文件还需要做兼容那些处理
实际开发用的是这种
"browserslist":["last 2 version","> 1%","not dead"]
Css压缩
1.下载包
npm i css-minimizer-webpack-plugin -D
2.配置webpack.prod.js文件
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")//定义一个函数抽取重复的代码 用来获取处理样式的loader
function getStyleLoader(pre){return [ //执行顺序,从右到左(从下到上)MiniCssExtractPlugin.loader, //提取css成单独文件"css-loader", //将css资源编译成commonjs的模块到js中{loader:"postcss-loader",options:{ //配置项postcssOptions:{plugins:["postcss-preset-env",//能解决大多数兼容性问题]}}},pre,].filter(Boolean);
}module.exports={//入口entry:'./src/main.js', //相对路径//输出output:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:path.resolve(__dirname,'../dist'),//绝对路径//入口文件打包输出文件名filename:'static/js/main.js',//原理,在打包前,将path整个目录内容清空,再进行打包clean:true, //自动清空上次打包内容},//加载器module:{rules:[//loader的配置{test:/\.css$/i, //只检测.css结尾的文件use:getStyleLoader(),},{test: /\.less$/i,use:getStyleLoader('less-loader'),},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},generator:{//输出图片名称//[hash:10] hash值取前10位filename:"static/images/[hash:10][ext][query]"}},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",generator:{//输出名称filename:"static/media/[hash:10][ext][query]"}},{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行// options:{// presets:["@babel/preset-env"]// }}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),}),new HtmlWebpackPlugin({//模板。以public/index.html文件创建新的html文件//新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源template:path.resolve(__dirname,"../public/index.html")}),new MiniCssExtractPlugin({filename:'static/css/main.css'}),new CssMinimizerPlugin(),],//模式mode:'production',
}
html压缩
(默认生成模式已经开启了:html压缩和js压缩,不需要额外进行配置)
webpack高级配置
(其实就是进行webpack优化)
1.提升开发体验
2.提升打包构建速度
3.减少代码体积
4.优化代码运行性能
1.提升开发体验
SourceMap(源代码映射)是一个用来生成源代码与构建后代码一一映射的文件的方案。
它会生成一个xxx.map文件,里面包含源代码和构建后代码每一行,每一列的映射关系,当构建后代码出错了,会通过xxx.map文件,从构建后代码出错位置找到映射后源代码出错位置,从而让浏览器提示源代码文件出错位置,帮助我们更快的找到错误根源。
开发模式:cheap-module-source-map
优点:打包编辑速度快,只包含行映射
缺点:没有列映射
webpack.dev.js
//模式mode:'development',devtool:"cheap-module-source-map"
生产模式:source-map
优点:包含行/列映射
缺点:打包编辑速度更慢
webpack.prod.js
//模式mode:'production',devtool:"source-map"
2.提升打包构建速度
HotModuleReplacement(HMR/热模块替换):在程序运行中,替换,添加或删除模块,而无需重新加载整个页面。
基本配置 webpack.dev.js
//开发服务器:不会输出资源,在内存中编译打包devServer:{host:"localhost",//启动服务器域名port:"3000", //启动服务器端口号open:true,//是否自动打开浏览器hot:true,//开启HMR功能(只能用于开发环境,生成环境不需要了)默认值是true},
此时css样式经过style-loader处理,已经具备HMR功能了,但是js还不行。
main.js
import count from "./js/count";
import sum from "./js/sum";
//想要webpack打包资源,必须引入该资源
import './css/index.css'
import './css/iconfont.css'
console.log(count(2,1));
console.log(sum(1,2,3,4,5));if(module.hot){//判断是否支持热模块替换功能module.hot.accept("./js/count")module.hot.accept("./js/sum")
}
上面这样写很麻烦,所以实际开发我们会使用其他loader来解决(比如:vue-loader,react-hot-loader)
oneOf(就是只能匹配上一个loader,剩下的就不匹配了)
include/exclude(包含/排除)两者只能存在一个
{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)//include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行// options:{// presets:["@babel/preset-env"]// }}
cache(对Eslint检查和Babel编译结果进行缓存)
{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)//include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行options:{// presets:["@babel/preset-env"]cacheDirectory:true,//开启babel缓存cacheCompression:false,//关闭缓存文件压缩}}
//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),exclude:"node_modules", //默认值 cache:true,//开启缓存cacheLocation:path.resolve(__dirname,"../node_modules/.cache/eslintcache") //指定缓存文件}),
thead(多进程打包,开启电脑的多个进程同时干一件事,速度更快)
需要注意:请仅在特别耗时的操作中使用,因为每个进程启动就有大约为600ms左右开销。
我们启动进程的数量就是我们CPU的核数。
1.如何获取CPU的核数,因为每个电脑都不一样
//nodejs核心模块,直接使用
const os=require('os');
//cpu核数
const threads=os.cpus().length;
2.下载包
npm i thread-loader -D
3.配置
{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)//include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来use:[{loader:"thread-loader", //开启多进程options:{works:threads, //进程数量}},{loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行options:{// presets:["@babel/preset-env"]cacheDirectory:true,//开启babel缓存cacheCompression:false,//关闭缓存文件压缩}}]}
//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),exclude:"node_modules", //默认值 cache:true,//开启缓存cacheLocation:path.resolve(__dirname,"../node_modules/.cache/eslintcache"), //指定缓存文件threads,//开启多进程和设置进程数量}),new HtmlWebpackPlugin({//模板。以public/index.html文件创建新的html文件//新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源template:path.resolve(__dirname,"../public/index.html")}),new MiniCssExtractPlugin({filename:'static/css/main.css'}),// new CssMinimizerPlugin(),// new TerserWebpackPlugin({// parallel:threads,//开启多进程和设置进程数量// })],optimization:{//压缩的操作minimizer:[//压缩cssnew CssMinimizerPlugin(),//压缩jsnew TerserWebpackPlugin({parallel:threads,//开启多进程和设置进程数量})]},
3.减少代码体积
tree Shaking(用于描述移除js中的没有使用上的代码)
webpack已经默认开启了这个功能,无需其他配置
注意:它依赖 ES模块化
babel
1.下载包
npm i @babel/plugin-transform-runtime -D
@babel/plugin-transform-runtime(禁用了Babel自动对每个文件的runtime注入,而是引入,并且使所有辅助代码从这里引用)
{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)//include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来use:[{loader:"thread-loader", //开启多进程options:{works:threads, //进程数量}},{loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行options:{// presets:["@babel/preset-env"]cacheDirectory:true,//开启babel缓存cacheCompression:false,//关闭缓存文件压缩plugins:['@babel/plugin-transform-runtime'],//减少代码体积}}]}
image Minimizer(用来压缩图片的插件)
注意:如果项目中图片都是在线连接,那么就不需要了,本地项目静态图片才需要进行压缩
1.下载包
npm i image-minimizer-webpack-plugin imagemin -D
还有剩下包需要下载,有两种模式:
无损压缩
npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D
有损压缩
npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D
注意:有时候网络问题,需要多下载几次,不然就使用翻墙软件下载
2.配置,以无损压缩配置为例 打包的时候报错 不知道啥问题导致的
optimization:{//压缩的操作minimizer:[//压缩cssnew CssMinimizerPlugin(),//压缩jsnew TerserWebpackPlugin({parallel:threads,//开启多进程和设置进程数量}),//压缩图片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",},},],},],],},},}),]},
4.优化代码运行性能
code split(代码分割)
1.分割文件:将打包生成的文件进行分割,生成多个js文件
单入口
optimization:{//压缩的操作minimizer:[//压缩cssnew CssMinimizerPlugin(),//压缩jsnew TerserWebpackPlugin({parallel:threads,//开启多进程和设置进程数量}),],//代码分割配置splitChunks:{chunks:"all",//其他都用默认值}},
2.按需加载:需要哪个文件就加载哪个文件。
main.js 动态引入按需加载
import count from "./js/count";
import sum from "./js/sum";//想要webpack打包资源,必须引入该资源
import './css/index.css'
import './css/iconfont.css'
console.log(count(2,1));
console.log(sum(1,2,3,4,5));document.getElementById('btn').onclick=function(){//动态引入按需加载//eslint不能识别动态导入需要,需要额外追加配置import("./js/math").then(({mul})=>{console.log(mul(3,1));})
}if(module.hot){//判断是否支持热模块替换功能module.hot.accept("./js/count")module.hot.accept("./js/sum")
}
.eslintrc.js 解决动态语法导入报错
module.exports={//继承Eslint规则extends:['eslint:recommended'],env:{node:true,//启用node中全局变量browser:true,//启用浏览器中全局变量},parserOptions:{ecmaVersion:6, //语法环境ES6sourceType:'module' //es module},rules:{"no-var":2 ,//不能使用var定义变量},plugins:['import'] //解决动态语法导入报错
}
给模块命名
1.main.js
import count from "./js/count";
import sum from "./js/sum";//想要webpack打包资源,必须引入该资源
import './css/index.css'
import './css/iconfont.css'
console.log(count(2,1));
console.log(sum(1,2,3,4,5));document.getElementById('btn').onclick=function(){//动态引入按需加载//eslint不能识别动态导入需要,需要额外追加配置// /* webpackChunkName:"math" */ webpack魔法命名import(/* webpackChunkName:"math" */ "./js/math").then(({mul})=>{console.log(mul(3,1));})
}if(module.hot){//判断是否支持热模块替换功能module.hot.accept("./js/count")module.hot.accept("./js/sum")
}
2.配置webpack.prod.js文件
//输出output:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:path.resolve(__dirname,'../dist'),//绝对路径//入口文件打包输出文件名filename:'static/js/main.js',//给打包输出的其他文件命名chunkFilename:"static/js/[name].js",//原理,在打包前,将path整个目录内容清空,再进行打包clean:true, //自动清空上次打包内容},
统一命名 webpack.prod.js
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin=require("terser-webpack-plugin")
// const ImageMinimizerPlugin=require("image-minimizer-webpack-plugin")//nodejs核心模块,直接使用
const os=require('os');
//cpu核数
const threads=os.cpus().length;
//定义一个函数抽取重复的代码 用来获取处理样式的loader
function getStyleLoader(pre){return [ //执行顺序,从右到左(从下到上)MiniCssExtractPlugin.loader, //提取css成单独文件"css-loader", //将css资源编译成commonjs的模块到js中{loader:"postcss-loader",options:{ //配置项postcssOptions:{plugins:["postcss-preset-env",//能解决大多数兼容性问题]}}},pre,].filter(Boolean);
}module.exports={//入口entry:'./src/main.js', //相对路径//输出output:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:path.resolve(__dirname,'../dist'),//绝对路径//入口文件打包输出文件名filename:'static/js/[name].js',//给打包输出的其他文件命名chunkFilename:"static/js/[name].chunk.js",//图片,字体等通过type:asset处理资源命名方式assetModuleFilename:"static/media/[hash:10][ext][query]",//原理,在打包前,将path整个目录内容清空,再进行打包clean:true, //自动清空上次打包内容},//加载器module:{rules:[//loader的配置{//每个文件只能被其中一个loader配置处理oneOf:[{test:/\.css$/i, //只检测.css结尾的文件use:getStyleLoader(),},{test: /\.less$/i,use:getStyleLoader('less-loader'),},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},// generator:{// //输出图片名称// //[hash:10] hash值取前10位// filename:"static/images/[hash:10][ext][query]"// }},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",// generator:{// //输出名称// filename:"static/media/[hash:10][ext][query]"// }},{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)//include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来use:[{loader:"thread-loader", //开启多进程options:{works:threads, //进程数量}},{loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行options:{// presets:["@babel/preset-env"]cacheDirectory:true,//开启babel缓存cacheCompression:false,//关闭缓存文件压缩plugins:['@babel/plugin-transform-runtime'],//减少代码体积}}]}]}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),exclude:"node_modules", //默认值 cache:true,//开启缓存cacheLocation:path.resolve(__dirname,"../node_modules/.cache/eslintcache"), //指定缓存文件threads,//开启多进程和设置进程数量}),new HtmlWebpackPlugin({//模板。以public/index.html文件创建新的html文件//新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源template:path.resolve(__dirname,"../public/index.html")}),new MiniCssExtractPlugin({filename:'static/css/[name].css',chunkFilename:'static/css/[name].chunk.css'}),// new CssMinimizerPlugin(),// new TerserWebpackPlugin({// parallel:threads,//开启多进程和设置进程数量// })],optimization:{//压缩的操作minimizer:[//压缩cssnew CssMinimizerPlugin(),//压缩jsnew TerserWebpackPlugin({parallel:threads,//开启多进程和设置进程数量}),//压缩图片 以下代码打包报错 不知道哪里问题// 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",// },// },// ],// },// ],// ],// },// },// }),],//代码分割配置splitChunks:{chunks:"all",//其他都用默认值}},//模式mode:'production',devtool:"source-map"
}
preload(告诉浏览器立即加载资源) / prefetch(告诉浏览器在空闲时才开始加载资源)
共同点: 都只会加载资源,并不执行。都有缓存
区别:preload加载优先级高,prefetch加载优先级低。
preload只能加载当前页面需要使用的资源,prefetch可以加载当前页面资源,也可以加载下一个页面需要使用的资源。
下载包
npm install --save-dev @vue/preload-webpack-plugin
const PreloadWebpackPlugin=require("@vue/preload-webpack-plugin")
//插件plugins:[new PreloadWebpackPlugin({// rel:'preload',// as:'script',rel:'prefetch',})],
core-js(是专门用来做ES6以及以上的API的polyfill(垫片/补丁,就是用社区上提供的一段代码,让我们在不兼容某些新特性的浏览器上,使用该新特性))
下载包
npm i core-js
main.js
import count from "./js/count";
import sum from "./js/sum";
//完整引入
// import 'core-js'
//按需加载
// import 'core-js/es/promise'//想要webpack打包资源,必须引入该资源
import './css/index.css'
import './css/iconfont.css'
console.log(count(2,1));
console.log(sum(1,2,3,4,5));document.getElementById('btn').onclick=function(){//动态引入按需加载//eslint不能识别动态导入需要,需要额外追加配置// /* webpackChunkName:"math" */ webpack魔法命名import(/* webpackChunkName:"math" */ "./js/math").then(({mul})=>{console.log(mul(3,1));})
}if(module.hot){//判断是否支持热模块替换功能module.hot.accept("./js/count")module.hot.accept("./js/sum")
}new Promise((resolve)=>{setTimeout(()=>{resolve();},1000)
})
自动引入
文档
babel.config.js
module.exports={//智能预设,能够编译ES6语法presets:[["@babel/preset-env",{useBuiltIns:'usage',//按需加载自动引入corejs:3}]]
}
PWA(渐进式网络应用程序,在离线时应用程序能够继续运行功能) 兼容性比较差
下载包
npm i workbox-webpack-plugin -D
文档
配置main.js
import count from "./js/count";
import sum from "./js/sum";
//完整引入
// import 'core-js'
//按需加载
// import 'core-js/es/promise'//想要webpack打包资源,必须引入该资源
import './css/index.css'
import './css/iconfont.css'
console.log(count(2,1));
console.log(sum(1,2,3,4,5));document.getElementById('btn').onclick=function(){//动态引入按需加载//eslint不能识别动态导入需要,需要额外追加配置// /* webpackChunkName:"math" */ webpack魔法命名import(/* webpackChunkName:"math" */ "./js/math").then(({mul})=>{console.log(mul(3,1));})
}if(module.hot){//判断是否支持热模块替换功能module.hot.accept("./js/count")module.hot.accept("./js/sum")
}new Promise((resolve)=>{setTimeout(()=>{resolve();},1000)
})const arr=[1,2,3,4];
console.log(arr.includes(1));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);});});}
//插件plugins:[new WorkboxPlugin.GenerateSW({//这些选项帮助快速启用 ServiceWorkers//不允许遗留任何‘旧的’ ServiceWorkersclientsClaim:true,skipWaiting:true})],
npm i serve -g 全局安装
serve dist 运行
Notwork——》开启 Offline 离线环境 看效果
webpack.prod.js完整代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin=require("terser-webpack-plugin")
// const ImageMinimizerPlugin=require("image-minimizer-webpack-plugin")
const PreloadWebpackPlugin=require("@vue/preload-webpack-plugin")
const WorkboxPlugin=require('workbox-webpack-plugin')
//nodejs核心模块,直接使用
const os=require('os');
//cpu核数
const threads=os.cpus().length;
//定义一个函数抽取重复的代码 用来获取处理样式的loader
function getStyleLoader(pre){return [ //执行顺序,从右到左(从下到上)MiniCssExtractPlugin.loader, //提取css成单独文件"css-loader", //将css资源编译成commonjs的模块到js中{loader:"postcss-loader",options:{ //配置项postcssOptions:{plugins:["postcss-preset-env",//能解决大多数兼容性问题]}}},pre,].filter(Boolean);
}module.exports={//入口entry:'./src/main.js', //相对路径//输出output:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:path.resolve(__dirname,'../dist'),//绝对路径//入口文件打包输出文件名filename:'static/js/[name].js',//给打包输出的其他文件命名chunkFilename:"static/js/[name].chunk.js",//图片,字体等通过type:asset处理资源命名方式assetModuleFilename:"static/media/[hash:10][ext][query]",//原理,在打包前,将path整个目录内容清空,再进行打包clean:true, //自动清空上次打包内容},//加载器module:{rules:[//loader的配置{//每个文件只能被其中一个loader配置处理oneOf:[{test:/\.css$/i, //只检测.css结尾的文件use:getStyleLoader(),},{test: /\.less$/i,use:getStyleLoader('less-loader'),},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},// generator:{// //输出图片名称// //[hash:10] hash值取前10位// filename:"static/images/[hash:10][ext][query]"// }},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",// generator:{// //输出名称// filename:"static/media/[hash:10][ext][query]"// }},{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)//include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来use:[{loader:"thread-loader", //开启多进程options:{works:threads, //进程数量}},{loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行options:{// presets:["@babel/preset-env"]cacheDirectory:true,//开启babel缓存cacheCompression:false,//关闭缓存文件压缩plugins:['@babel/plugin-transform-runtime'],//减少代码体积}}]}]}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),exclude:"node_modules", //默认值 cache:true,//开启缓存cacheLocation:path.resolve(__dirname,"../node_modules/.cache/eslintcache"), //指定缓存文件threads,//开启多进程和设置进程数量}),new HtmlWebpackPlugin({//模板。以public/index.html文件创建新的html文件//新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源template:path.resolve(__dirname,"../public/index.html")}),new MiniCssExtractPlugin({filename:'static/css/[name].css',chunkFilename:'static/css/[name].chunk.css'}),// new CssMinimizerPlugin(),// new TerserWebpackPlugin({// parallel:threads,//开启多进程和设置进程数量// })new PreloadWebpackPlugin({// rel:'preload',// as:'script',rel:'prefetch',}),new WorkboxPlugin.GenerateSW({//这些选项帮助快速启用 ServiceWorkers//不允许遗留任何‘旧的’ ServiceWorkersclientsClaim:true,skipWaiting:true})],optimization:{//压缩的操作minimizer:[//压缩cssnew CssMinimizerPlugin(),//压缩jsnew TerserWebpackPlugin({parallel:threads,//开启多进程和设置进程数量}),//压缩图片 以下代码打包报错 不知道哪里问题// 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",// },// },// ],// },// ],// ],// },// },// }),],//代码分割配置splitChunks:{chunks:"all",//其他都用默认值},runtimeChunk:{name:(entrypoint)=>`runtime~${entrypoint.name}.js`,}},//模式mode:'production',devtool:"source-map"
}
webpack.dev.js完整代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')//nodejs核心模块,直接使用
const os=require('os');
//cpu核数
const threads=os.cpus().length;
module.exports={//入口entry:'./src/main.js', //相对路径//输出output:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:path.resolve(__dirname,'../dist'),//绝对路径//入口文件打包输出文件名filename:'static/js/[name].js',//给打包输出的其他文件命名chunkFilename:"static/js/[name].chunk.js",//图片,字体等通过type:asset处理资源命名方式assetModuleFilename:"static/media/[hash:10][ext][query]",//原理,在打包前,将path整个目录内容清空,再进行打包clean:true, //自动清空上次打包内容},//加载器module:{rules:[//loader的配置{//每个文件只能被其中一个loader配置处理oneOf:[{test:/\.css$/i, //只检测.css结尾的文件use:[ //执行顺序,从右到左(从下到上)"style-loader", //将js中css通过创建style标签添加html文件中生效"css-loader" //将css资源编译成commonjs的模块到js中]},{test: /\.less$/i,use: [// 使用多个loader'style-loader','css-loader','less-loader', //将less编译成css文件],},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},// generator:{// //输出图片名称// //[hash:10] hash值取前10位// filename:"static/images/[hash:10][ext][query]"// }},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",// generator:{// //输出名称// filename:"static/media/[hash:10][ext][query]"// }},{test:/\.js$/, //处理字体图标资源或者其他资源exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)//include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来use:[{loader:"thread-loader", //开启多进程options:{works:threads, //进程数量}},{loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行options:{// presets:["@babel/preset-env"]cacheDirectory:true,//开启babel缓存cacheCompression:false,//关闭缓存文件压缩plugins:['@babel/plugin-transform-runtime'],//减少代码体积}}]}]}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),exclude:"node_modules", //默认值 cache:true,//开启缓存cacheLocation:path.resolve(__dirname,"../node_modules/.cache/eslintcache"), //指定缓存文件threads,//开启多进程和设置进程数量}),new HtmlWebpackPlugin({//模板。以public/index.html文件创建新的html文件//新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源template:path.resolve(__dirname,"../public/index.html")})],//开发服务器:不会输出资源,在内存中编译打包devServer:{host:"localhost",//启动服务器域名port:"3000", //启动服务器端口号open:true,//是否自动打开浏览器hot:true,//开启HMR功能(只能用于开发环境,生成环境不需要了)默认值是true},//模式mode:'development',devtool:"cheap-module-source-map",
}
vueCli开发模式配置vue3
npm init -y
安装
npm install -D vue-loader vue-template-compiler
配置webpack.dev.js 开发模式
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const {DefinePlugin} =require("webpack")
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const { VueLoaderPlugin}=require('vue-loader')
//定义一个函数抽取重复的代码 用来获取处理样式的loader
function getStyleLoader(pre){return [ //执行顺序,从右到左(从下到上)"vue-style-loader", //提取css成单独文件"css-loader", //将css资源编译成commonjs的模块到js中{loader:"postcss-loader",options:{ //配置项postcssOptions:{plugins:["postcss-preset-env",//能解决大多数兼容性问题]}}},pre,].filter(Boolean);
}
module.exports={//入口entry:'./src/main.js', //相对路径//输出output:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:undefined,//绝对路径//入口文件打包输出文件名filename:'static/js/[name].js',//给打包输出的其他文件命名chunkFilename:"static/js/[name].chunk.js",//图片,字体等通过type:asset处理资源命名方式assetModuleFilename:"static/media/[hash:10][ext][query]"},//加载器module:{rules:[//loader的配置{test:/\.css$/, //只检测.css结尾的文件use:getStyleLoader(),},{test: /\.less$/,use:getStyleLoader('less-loader'),},{test: /\.s[ac]ss$/,use:getStyleLoader('sass-loader'),},{test: /\.styl$/,use:getStyleLoader('stylus-loader'),},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",},{test:/\.js$/, //处理字体图标资源或者其他资源include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行options:{cacheDirectory:true,//开启babel缓存cacheCompression:false,//关闭缓存文件压缩}},{test:/\.vue$/,loader:'vue-loader'}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),exclude:"node_modules", //默认值 cache:true,//开启缓存cacheLocation:path.resolve(__dirname,"../node_modules/.cache/.eslintcache"), //指定缓存文件}),new HtmlWebpackPlugin({//模板。以public/index.html文件创建新的html文件//新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源template:path.resolve(__dirname,"../public/index.html")}),new VueLoaderPlugin(),//定义环境变量 cross-env定义的环境变量给打包工具使用//DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告的问题new DefinePlugin({__VUE_OPTIONS_API__:true,__VUE_PROD_DEVTOOLS__:false})],//开发服务器:不会输出资源,在内存中编译打包devServer:{host:"localhost",//启动服务器域名port:"4000", //启动服务器端口号open:true,//是否自动打开浏览器hot:true,//开启HMR功能(只能用于开发环境,生成环境不需要了)默认值是truehistoryApiFallback:true, //解决前端路由刷新404问题},optimization:{//代码分割配置splitChunks:{chunks:"all",//其他都用默认值},runtimeChunk:{name:(entrypoint)=>`runtime~${entrypoint.name}.js`,}},//webpack解析模块加载选项resolve:{//自动补全文件扩展名extensions:['.js','.json','.vue']},//模式mode:'development',devtool:"cheap-module-source-map",
}
安装依赖
npm i eslint-webpack-plugin html-webpack-plugin vue-style-loader css-loader postcss-loader postcss-preset-env -D
npm i less-loader sass-loader sass stylus-loader babel-loader vue-loader webpack webpack-cli webpack-dev-server -D
.eslintrc.js 配置
module.exports={root:true,env:{node:true,},extends:['plugin:vue/vue3-essential','eslint:recommended'],parserOptions:{parser:'@babel/eslint-parser'}
};
npm i @babel/eslint-parser -D
babel.config.js 配置
module.exports={presets:["@vue/cli-plugin-babel/preset"]
}
npm i @vue/cli-plugin-babel -D
npm i vue (默认是vue3的版本)
npm i cross-env -D
npm i eslint-plugin-vue -D
npm i vue-router
生产模式 webpack.prod.js
npm i mini-css-extract-plugin css-minimizer-webpack-plugin copy-webpack-plugin -D
下载图片
npm i image-minimizer-webpack-plugin imagemin -D
无损下载
npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D
不知道为什么,下载图片老是下载失败
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin=require("terser-webpack-plugin")
// const ImageMinimizerPlugin=require("image-minimizer-webpack-plugin")
const CopyPlugin=require('copy-webpack-plugin')
const { VueLoaderPlugin}=require('vue-loader')
const {DefinePlugin} =require("webpack")
//定义一个函数抽取重复的代码 用来获取处理样式的loader
function getStyleLoader(pre){return [ //执行顺序,从右到左(从下到上)MiniCssExtractPlugin.loader, //提取css成单独文件"css-loader", //将css资源编译成commonjs的模块到js中{loader:"postcss-loader",options:{ //配置项postcssOptions:{plugins:["postcss-preset-env",//能解决大多数兼容性问题]}}},pre,].filter(Boolean);
}module.exports={//入口entry:'./src/main.js', //相对路径//输出output:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:path.resolve(__dirname,'../dist'),//绝对路径//入口文件打包输出文件名filename:'static/js/[name].[contenthash:10].js',//给打包输出的其他文件命名chunkFilename:"static/js/[name].[contenthash:10].chunk.js",//图片,字体等通过type:asset处理资源命名方式assetModuleFilename:"static/media/[hash:10][ext][query]",//原理,在打包前,将path整个目录内容清空,再进行打包clean:true, //自动清空上次打包内容},//加载器module:{rules:[//loader的配置{test:/\.css$/, //只检测.css结尾的文件use:getStyleLoader(),},{test: /\.less$/,use:getStyleLoader('less-loader'),},{test: /\.s[ac]ss$/,use:getStyleLoader('sass-loader'),},{test: /\.styl$/,use:getStyleLoader('stylus-loader'),},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",},{test:/\.js$/, //处理字体图标资源或者其他资源include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行options:{cacheDirectory:true,//开启babel缓存cacheCompression:false,//关闭缓存文件压缩}},{test:/\.vue$/,loader:'vue-loader'}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),exclude:"node_modules", //默认值 cache:true,//开启缓存cacheLocation:path.resolve(__dirname,"../node_modules/.cache/.eslintcache"), //指定缓存文件}),new HtmlWebpackPlugin({template:path.resolve(__dirname,"../public/index.html")}),new MiniCssExtractPlugin({filename:'static/css/[name].[contenthash:10].css',chunkFilename:'static/css/[name].[contenthash:10].chunk.css'}),new CopyPlugin({patterns:[{from:path.resolve(__dirname,"../public"),to:path.resolve(__dirname,"../dist"),globOptions:{//忽略index.html文件ignore:["**/index.html"]}}]}),new VueLoaderPlugin(),//定义环境变量 cross-env定义的环境变量给打包工具使用//DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告的问题new DefinePlugin({__VUE_OPTIONS_API__:true,__VUE_PROD_DEVTOOLS__:false})],optimization:{//压缩的操作minimizer:[//压缩cssnew CssMinimizerPlugin(),//压缩jsnew TerserWebpackPlugin(),//压缩图片 以下代码打包报错 不知道哪里问题// 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",// },// },// ],// },// ],// ],// },// },// }),],//代码分割配置splitChunks:{chunks:"all",//其他都用默认值},runtimeChunk:{name:(entrypoint)=>`runtime~${entrypoint.name}.js`,},},//模式mode:'production',devtool:"source-map",//webpack解析模块加载选项resolve:{//自动补全文件扩展名extensions:['.js','.json','.vue']},
}
package.json
"scripts": {"start": "npm run dev","dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.dev.js","build": "cross-env NODE_ENV=production webpack --config ./config/webpack.prod.js"},
合并配置
webpack.config.js
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin=require("terser-webpack-plugin")
// const ImageMinimizerPlugin=require("image-minimizer-webpack-plugin")
const CopyPlugin=require('copy-webpack-plugin')
const { VueLoaderPlugin}=require('vue-loader')
const {DefinePlugin} =require("webpack")const isProduction=process.env.NODE_ENV==='production';//定义一个函数抽取重复的代码 用来获取处理样式的loader
function getStyleLoader(pre){return [ //执行顺序,从右到左(从下到上)isProduction ? MiniCssExtractPlugin.loader : 'vue-style-loader', //提取css成单独文件"css-loader", //将css资源编译成commonjs的模块到js中{loader:"postcss-loader",options:{ //配置项postcssOptions:{plugins:["postcss-preset-env",//能解决大多数兼容性问题]}}},pre,].filter(Boolean);
}module.exports={//入口entry:'./src/main.js', //相对路径//输出output:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:isProduction ? path.resolve(__dirname,'../dist') : undefined,//绝对路径//入口文件打包输出文件名filename:isProduction ? 'static/js/[name].[contenthash:10].js' : 'static/js/[name].js',//给打包输出的其他文件命名chunkFilename:isProduction ? "static/js/[name].[contenthash:10].chunk.js":"static/js/[name].chunk.js",//图片,字体等通过type:asset处理资源命名方式assetModuleFilename:"static/media/[hash:10][ext][query]",//原理,在打包前,将path整个目录内容清空,再进行打包clean:true, //自动清空上次打包内容},//加载器module:{rules:[//loader的配置{test:/\.css$/, //只检测.css结尾的文件use:getStyleLoader(),},{test: /\.less$/,use:getStyleLoader('less-loader'),},{test: /\.s[ac]ss$/,use:getStyleLoader('sass-loader'),},{test: /\.styl$/,use:getStyleLoader('stylus-loader'),},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",},{test:/\.js$/, //处理字体图标资源或者其他资源include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行options:{cacheDirectory:true,//开启babel缓存cacheCompression:false,//关闭缓存文件压缩}},{test:/\.vue$/,loader:'vue-loader'}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),exclude:"node_modules", //默认值 cache:true,//开启缓存cacheLocation:path.resolve(__dirname,"../node_modules/.cache/.eslintcache"), //指定缓存文件}),new HtmlWebpackPlugin({template:path.resolve(__dirname,"../public/index.html")}),isProduction && new MiniCssExtractPlugin({filename:'static/css/[name].[contenthash:10].css',chunkFilename:'static/css/[name].[contenthash:10].chunk.css'}),isProduction && new CopyPlugin({patterns:[{from:path.resolve(__dirname,"../public"),to:path.resolve(__dirname,"../dist"),globOptions:{//忽略index.html文件ignore:["**/index.html"]}}]}),new VueLoaderPlugin(),//定义环境变量 cross-env定义的环境变量给打包工具使用//DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告的问题new DefinePlugin({__VUE_OPTIONS_API__:true,__VUE_PROD_DEVTOOLS__:false})].filter(Boolean),optimization:{minimize:isProduction,//压缩的操作minimizer:[//压缩cssnew CssMinimizerPlugin(),//压缩jsnew TerserWebpackPlugin(),//压缩图片 以下代码打包报错 不知道哪里问题// 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",// },// },// ],// },// ],// ],// },// },// }),],//代码分割配置splitChunks:{chunks:"all",//其他都用默认值},runtimeChunk:{name:(entrypoint)=>`runtime~${entrypoint.name}.js`,},},//模式mode:isProduction ? 'production' :'development',devtool:isProduction ? "source-map" :"cheap-module-source-map",//webpack解析模块加载选项resolve:{//自动补全文件扩展名extensions:['.js','.json','.vue']},//开发服务器:不会输出资源,在内存中编译打包devServer:{host:"localhost",//启动服务器域名port:"4000", //启动服务器端口号open:true,//是否自动打开浏览器hot:true,//开启HMR功能(只能用于开发环境,生成环境不需要了)默认值是truehistoryApiFallback:true, //解决前端路由刷新404问题},
}
package.json
"scripts": {"start": "npm run dev","dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.config.js","build": "cross-env NODE_ENV=production webpack --config ./config/webpack.config.js"},
优化配置
npm install element-plus --save
按需引入
npm install -D unplugin-vue-components unplugin-auto-import
报错解决
报错 1:AutoImport is not a function
解决:是 unplugin-auto-import版本高了,我用的0.17.3。后面降版本,改成0.16.7,这个问题就不报错了。
报错2:Components is not a function
解决:unplugin-vue-components 版本也高了,从0.27.0 降到了 0.25.2 ,就能正常运行了
webpack.config.js
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin=require("terser-webpack-plugin")
// const ImageMinimizerPlugin=require("image-minimizer-webpack-plugin")
const CopyPlugin=require('copy-webpack-plugin')
const { VueLoaderPlugin}=require('vue-loader')
const {DefinePlugin} =require("webpack")const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')const isProduction=process.env.NODE_ENV==='production';//定义一个函数抽取重复的代码 用来获取处理样式的loader
function getStyleLoader(pre){return [ //执行顺序,从右到左(从下到上)isProduction ? MiniCssExtractPlugin.loader : 'vue-style-loader', //提取css成单独文件"css-loader", //将css资源编译成commonjs的模块到js中{loader:"postcss-loader",options:{ //配置项postcssOptions:{plugins:["postcss-preset-env",//能解决大多数兼容性问题]}}},pre && {loader:pre,options:pre === 'sass-loader'? {additionalData : `@use "@/styles/element/index.scss" as *;`,}: {},},].filter(Boolean);
}module.exports={//入口entry:'./src/main.js', //相对路径//输出output:{//所有文件的输出路径//__dirname nodejs的变量,代表当前文件的文件夹目录path:isProduction ? path.resolve(__dirname,'../dist') : undefined,//绝对路径//入口文件打包输出文件名filename:isProduction ? 'static/js/[name].[contenthash:10].js' : 'static/js/[name].js',//给打包输出的其他文件命名chunkFilename:isProduction ? "static/js/[name].[contenthash:10].chunk.js":"static/js/[name].chunk.js",//图片,字体等通过type:asset处理资源命名方式assetModuleFilename:"static/media/[hash:10][ext][query]",//原理,在打包前,将path整个目录内容清空,再进行打包clean:true, //自动清空上次打包内容},//加载器module:{rules:[//loader的配置{test:/\.css$/, //只检测.css结尾的文件use:getStyleLoader(),},{test: /\.less$/,use:getStyleLoader('less-loader'),},{test: /\.s[ac]ss$/,use:getStyleLoader('sass-loader'),},{test: /\.styl$/,use:getStyleLoader('stylus-loader'),},{test:/\.(png|jpe?g|glf|webp|svg)$/,type:"asset",parser:{dataUrlCondition:{//小于10kb的图片转base64//优点,减少请求数量,缺点,体积会更大maxSize:10 * 1024,//10kb}},},{test:/\.(ttf|woff2?|mp3|mp4|avi)$/, //处理字体图标资源或者其他资源type:"asset/resource",},{test:/\.js$/, //处理字体图标资源或者其他资源include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来loader:'babel-loader',//写这里也行,写外面babel.config.js里面也行options:{cacheDirectory:true,//开启babel缓存cacheCompression:false,//关闭缓存文件压缩}},{test:/\.vue$/,loader:'vue-loader',options:{//开启缓存cacheDirectory:path.resolve(__dirname,"../node_modules/.cache/vue-loader"),}}]},//插件plugins:[//plugin的配置new ESLintPlugin({//检测哪些文件context:path.resolve(__dirname,"../src"),exclude:"node_modules", //默认值 cache:true,//开启缓存cacheLocation:path.resolve(__dirname,"../node_modules/.cache/.eslintcache"), //指定缓存文件}),new HtmlWebpackPlugin({template:path.resolve(__dirname,"../public/index.html")}),isProduction && new MiniCssExtractPlugin({filename:'static/css/[name].[contenthash:10].css',chunkFilename:'static/css/[name].[contenthash:10].chunk.css'}),isProduction && new CopyPlugin({patterns:[{from:path.resolve(__dirname,"../public"),to:path.resolve(__dirname,"../dist"),globOptions:{//忽略index.html文件ignore:["**/index.html"]}}]}),new VueLoaderPlugin(),//定义环境变量 cross-env定义的环境变量给打包工具使用//DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告的问题new DefinePlugin({__VUE_OPTIONS_API__:true,__VUE_PROD_DEVTOOLS__:false}),//按需加载element-plusAutoImport({resolvers: [ElementPlusResolver()],}),Components({resolvers: [ElementPlusResolver({//自定义主题,引入sassimportStyle:'sass'})],}),].filter(Boolean),optimization:{minimize:isProduction,//压缩的操作minimizer:[//压缩cssnew CssMinimizerPlugin(),//压缩jsnew TerserWebpackPlugin(),//压缩图片 以下代码打包报错 不知道哪里问题// 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",// },// },// ],// },// ],// ],// },// },// }),],//代码分割配置splitChunks:{chunks:"all",//其他都用默认值cacheGroups:{vue:{test:/[\\/]node_modules[\\/]vue(.*)?[\\/]/,name:'vue-chunk',priority:40,},elementPlus:{test:/[\\/]node_modules[\\/]element-plus[\\/]/,name:'elementPlus-chunk',priority:30,},libs:{test:/[\\/]node_modules[\\/]/,name:'libs-chunk',priority:20,},}},runtimeChunk:{name:(entrypoint)=>`runtime~${entrypoint.name}.js`,},},//模式mode:isProduction ? 'production' :'development',devtool:isProduction ? "source-map" :"cheap-module-source-map",//webpack解析模块加载选项resolve:{//自动补全文件扩展名extensions:['.js','.json','.vue'],//路径别名alias:{'@':path.resolve(__dirname,'../src'),}},//开发服务器:不会输出资源,在内存中编译打包devServer:{host:"localhost",//启动服务器域名port:"4000", //启动服务器端口号open:true,//是否自动打开浏览器hot:true,//开启HMR功能(只能用于开发环境,生成环境不需要了)默认值是truehistoryApiFallback:true, //解决前端路由刷新404问题},//关闭性能分析,提升打包速度performance:false,
}
自定义主题 styles/element/index.scss
// styles/element/index.scss
@forward 'element-plus/theme-chalk/src/common/var.scss' with ($colors: ('primary': ('base': green,),),
);