webpack模块打包
...大约 14 分钟
webpack模块打包
什么是打包工具
- 打包并优化项目文件,节省开发效率
额外知识拓展
JS文件包含另一个文件使用require方法
require('另一个文件的路径')
JS文件如需在index.js入口文件处引入,需要在当前JS页面内暴露
module.exports = {
//具体语法
}
- 插件使用时需要在webpack.config.js顶部引入
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
//声明变量MiniCssExtractPlugin为require引入的mini-css-extract-plugin插件
- 并在plugin处new对应的插件名
new MiniCssExtractPlugin(options:{
template:'',
filename: '
'})
- Gzip压缩编译????? 点此前往查看
webpack基本概念
- 安装时需要安装webpack和其脚手架webpack-cli
- 没配置完一项,需要终端输入webpack来执行相关命令
- webpack原理概念图
1. 树结构:
- 在一个入口文件中引入所有资源,形成所有依赖关系树状图
2. 模块:
- 模块就是多个文件打包成一个模块,可以是ES6模块,commonJS模块等,对于webpack来说,就是(css,img,.....)
**3. chunk:
- 打包过程中被操作的模块文件叫做chunk,例如异步加载一个模块就是一个chunk
**4. bundel:
- 是最后打包后的文件,可以和chunk长的一样,但是大部分情况下他是多个chunk的集合
- 为了优化最后生产出的bundle数量可能不等于chunk的数量
- 因为有可能多个chunk被组合到了一个bundel中
webpack报错
- webpack安装好后,运行webpack -v会提示错误,或者打包时提示错误
- 解决方法:
- 以管理员身份运行IDE
- 执行:get-ExecutionPolicy,显示Restricted,表示状态是禁止
- 执行:set-ExecutionPolicy RemoteSigned
- 这时再执行get-ExecutionPolicy,就显示RemoteSigned
webpack核心概念
- 打包时必须要暴露文件,里面语法为json格式(键,值模式)
- 五个核心配置项必要包含在暴露语法内
module.exports = {
//具体语法
}
- 项目目录下新建一个JS(webpack.config.js)文件
- 建议采用官方默认的名称,如不用,则每次都需要指定,很繁琐
1. 入口
- entry,入口指示webpack以哪个文件作为入口起点开始打包,分布并构建依赖图
entry: "入口文件具体路径",
2. 输出
- output,输出指示webpack打包后的资源(bundles)输出到哪里,以及如何命名
- 语法格式为json格式,filename为输出的文件名称,path为输出文件的具体路径
- path指定路径时需要调用node.js的包,具体语法如下:
2-1. webpack.config.js文件顶部接收resolve函数
const {resolve} = require('path');
2-2. 在output的path处调用resolve方法
output: {
filename: "输出文件的名称",
path: resolve(__dirname, '路径目录的名称')
//调用nodejs的resolve方法来指定输出目录
},
3. 翻译
- loader(翻译)默认情况下,webpack只能处理js,json格式的文件,
- 使用loader可以让webpack处理非js,json文件
- 使用module方法
- 示例:
module: {
rules: [
{ //具体语法
test: /\.css$/, //正则匹配文件类型
use:['style-loader','css-loader'] //多个loader
}
]
},
4. 插件
- plugins(插件)可以用于执行范围更广的任务,包括打包优化,压缩,重新定义环境等,语法格式为数组模式
plugins: [
new HtmlWebpackPlugin()
]
5. 模式
- mode(模式)指示webpack使用相应依赖模式的配置
- 指示相应依赖模式时,会自动启用一些对应的插件
- 开发依赖模式插件较少,生产模式较多
mode:'development'
webpack多入口与多出口
1. 字符串模式,单入口
- 入口文件需要与要打包的文件形成关联,才可打包
- 如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,chunk的名称是默认的(出口指定的名称)
2. 数组模式,多入口
- 写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是一个bundle
entry: ["具体入口路径1","具体入口路径2"],
3. 对象模式,多入口
- 写多个入口文件,有几个入口文件就会生成几个chunk,并输出几个bundle,chunk的名称是对象的key(键)如下示例1语法
- 需要在output(输出)filename下更改为以下示例2语法
- 示例1:
entry: {
one:'./具体入口路径', //左边为key(键)
two:'./具体入口路径'
},
- 示例2
output: {
filename: "[name].js", //
path: resolve(__dirname,'build')
},
4. 特殊用法,对象和数组混合
entry: {
//数组多入口
onea:["具体入口路径1","具体入口路径2"],
//单入口
twob:"具体入口路径3"
},
打包html资源
- 需要单独使用插件(plugins)对html文件进行处理
- npm安装html-webpack-plugin插件
- -D为生产依赖的缩写
npm i html-webpack-plugin -D
- 需要通过webpack.config.js文件里在顶部添加使用require方法
- 示例1:
const HtmlWebpackPlugin = require("html-webpack-plugin");
- webpack.config.js里plugins使用构造方法来引用此插件
- 默认情况下,会创建一个空的html,目的就是自动引入打包的资源(js/css)
- 示例2:
plugins: [
new HtmlWebpackPlugin()//构造方法
]
- 如果需要自己指定打包的html,生成自己指定的文件名
- 则需要在构造方法中加json对象的参数options
- 在options里使用minfy方法还可移除空格和移除注释
- 移除空格只会删除html格式的空格,不会删除标签内内容的空格
- minfy为对象形式
- 示例3:
plugins: [
new HtmlWebpackPlugin(options:{
template: "指定需要打包的html文件原路径",
filename: "指定打包好的文件名称"
minify: {
collapseWhitespace:true, //移除空格 removeComments:true //移除注释
}
})
],
注意:webstorm中,new HtmlWebpackPlugin后手写options属性时会报错,正确做法是在new HtmlWebpackPlugin后面括号内写入花括号会自动生产options属性
打包多个html文件
- 打包多个html文件时,需要添加多个new HtmlWebpackPlugin
- 给每个打包的html文件指定引入的build时,需添加chunk属性
- 如下示例:
//第一个打包的html文件
new HtmlWebpackPlugin( options:{
template: "./src/index.html", //需要打包的路径
filename: "index.html", //指定打包好的文件名称
chunks: ['index','vendor'], //指定引入其它文件的build名称
minify: {
collapseWhitespace:true, //移除空格
removeComments:true //移除注释
}
}),
//第二个打包的html文件
new HtmlWebpackPlugin(options:{
template: "./src/cart.html", //需要打包的路径
filename: "cart.html", //指定打包好的文件名称
chunks: ['cart','vendor'], //指定引入其它文件的build名称
minify: {
collapseWhitespace:true, //移除空格
removeComments:true //移除注释
}
})
//指定引入其它文件的build(就是入口文件打包输出的文件)
entry: { //左边为build名称
vendor: ['./src/js/jquery.js','./src/js/common.js'], index:'./src/js/index.js',
cart:'./src/js/cart.js'
},
打包CSS资源
- 需要npm安装css-loader和style-loader
- css-loader的作用是把css资源打包到js文件中
- style-loader的作用是把打包好的js文件里的样式放到html里
- 单个loader可以直接loader属性使用
- 多个loader则需要使用数组形式,并匹配规则
- css文件需要先css-loader后syle-loader
- 规则是从右到左、从上到下
- 示例:
module: {
rules: [
{ //具体语法
test: /\.css$/, //正则匹配相关文件类型
use:['style-loader','css-loader'] //多个loader
loader: "css-loader" //单个loader
}
]
},
打包less和sass资源
- 打包less和sass文件时,都需要保留css-loader和style-loader
- 语法与打包css资源一致,只是多了less-loader和sass-loader
- 正则匹配sass文件类型时,需更改为正则匹配scss类型,而不是sass(sass有sass与scss俩种格式)
- 打包less
- 需要npm安装less包和less-loader
- 打包sass
- 需要npm安装node-sass包和sass-loader
- 打包less
提取css为单独文件
- style-loader默认会把css样式通过JS写入到html里
- 编译修改起来有时不太方便,可以使用MiniCssExtractPlugin.loader替换style-loader来提取css为单独文件,不需要引号引起来
- 不支持打包为多个build
- 需要npm安装mini-css-extract-plugin插件
- 示例:
new MiniCssExtractPlugin(options:{
template:'',
filename: ''
})
use:[MiniCssExtractPlugin.loader,'css-loader'],
处理CSS浏览器兼容性
- 需要使用postcss处理兼容性
- 同样适用于css/less/scss格式
- npm安装post-loader包和postcss-preset-env插件
- postcss有单独的文件(postcss.config.js)配置插件 1. 和webpack.config.js一样需要暴露出去
- 示例1:
module.exports = {
plugins:[
require('postcss-preset-env')()
]
}
2. 在webpack.config.js里loader处添加到最右面
- 默认执行顺序时,先处理兼容性,然后在执行其他的loader
- 会自动在postcss.config.js查找postcss-preset-env插件有没有
>use:[MiniCssExtractPlugin.loader,'css-loader', "postcss-loader"],
3. 指定兼容浏览器条件
- 在package.json里使用browerslist方法来指定规则
- browerslist可以选择对象与数组模式
- 对象模式可以分别指定开发依赖和运行依赖的规则
- 默认情况下建议使用数组模式,只指定运行依赖的条件
- 可以指定多条规则,如下示例2:
- 示例2:
"browerslist": [
"> 0.2%",//小于20%的浏览器都支持
"last 2 versions",//最新的2个浏览器版本
"not dead",//废弃的浏览器
]
压缩CSS内容
- 需要npm安装optimize-css-assets-webpack-plugin插件
- webpack.config.js顶部引入
- 然后plugins处new引入执行即可,如下示例1:
- 示例1:
new OptimizeCssAssetsWebpackPlugin()
打包图片资源
CSS里打包图片方法
- 需要npm安装url-loader包和file-loader包
- 俩个包互相是依赖关系,可以加载任何文件
- url-loader可以将图片转为base64字符串,能更快的加载图片
- 一旦图片过大,就需要使用file-loader加载本地图片
- base64格式为计算机把图片生成为二进制指令存储在服务器,但不会存储本地
- hash为计算机生成base64格式图片的名称,默认名很长,可以hash:10来指定具体名称长度,需要用[ ]包起来使用
- 故url-loader可以设置图片超过多少字节时,使用file-loader加载图片,如下示例
- 示例:
{
test:/\.(png|jpg|jpeg|gif)$/,
loader:'url-loader',
options{
publicPath:'样式内添加的路径名称,例如 ./images '
outputPath:'图片的路径' // 指定打包好的目录
limit:'1024 * 8' //1024个字节*8倍
以上为指定规则为8kb的图片打包为base64格式
name:'[name][hash:10].[ext]'
//打包后的名称,可以自定义指定规则
例如:保留原名称+hash名+格式
esModule:false, //老版本浏览器则需此属性
}
}
- base64格式为计算机把图片生成为二进制指令存储在服务器,但不会存储本地
- hash为计算机生成base64格式图片的名称,默认名很长,可以hash:10来指定具体名称长度,需要用[ ]包起来使用
- ext为默认原图片格式,需要用[ ]包起来使用,如需指定格式,则不需要 [ ]
- 打包图片资源时,16kb以下建议打包成base64格式
- 老版本浏览器则还需要在options最后一行添加esModele:false属性
Html里打包图片方法
- 如需HTML里打包图片路径,则需要再加一个loader 使用html-loader包来处理,只需要添加test规则指定.html格式
- options规则可以直接沿用之前添加的loader里的规则 而不需要在这个loader里重新编写,然后loader处使用html-loader,具体语法如下
- 示例2:
打包其它资源
- 字体图标库......等等
打包字体库
- 打包其他格式资源时,如格式较多,可使用exclude(排除正则)来匹配,排除已使用,已打包的格式
- 使用file-loader来打包其他资源
- options指定规则,和打包图片的options规则,不用加字节规则 如下示例:
- 示例:
{
exclude:/\.(js|json|html|css|less|scss|png|gif|ipg|jpeg)$/, //格式排除正则表达式
loader:"file-loader",
options: {
outputpath: "路径",// 打包好的路径
publicPath: " 路径",//css里的引用路径
name:"[name][hash:6].[ext]"//指定名称、hash名称长度、保留原格式
}
}
JS/JSON语法配置检查
- 默认情况下,js/json格式文件不需要单独处理
- 但是需要通过eslint单独检查一下JS语法配置
- 需要npm安装eslint、eslint-loader、eslint-config-airbnb-base、eslint-plugin-import缺一不可,互相形成依赖
- 下载安装好后需要在package.json里配置规则,具体语法如下:
- 示例:
"eslintConfig": {
"extends": "airbnb-base" //此规则较多使用
}
- 只检查当前项目写的js,不需要检查第三方JS插件包
- 只需要排除node_modules目录
- options里加上fix:true,可以自动检查后修改,程序逻辑除外
- 示例2:
{
test:/\.js$/, //正则匹配相关格式
exclude:/node_modules/, //正则排除第三方JS插件包
loader:'eslint-loader'
//使用此loader,自动调用package.json里eslintConfig规则
options: {
fix:true
}
}
- 如需遇到不想被检查并修复的语法,只需要在相关语法前加上以下规则注释,打包时会自动排除,如下示例3
- 一般console.log较多,因为只在开发时会用
- 示例3:
// eslint-disable-next-line
console.log("这是入口文件");
配置开发服务器
- 可以实时编译、实时浏览器预览
- 需要npm安装webpack-dev-server
- 安装后需终端输入webpack serve启动
- webpack5不支持自动编译,自动浏览器刷新,只能通过webpack.config.js里配置target:"web"项
- 配置target:"web"项后,先退出webpack secer后再次进入
- 然后浏览器输入localhost:相应的端口号
- 其他命令:
//此为更改端口开发服务器端口号
webpack serve --port 3003
- 通常可以直接在webpack.config.js里配置dev-server选项
- 包括端口号等等。具体语法如下:
- 示例:
devServer: {
port:3001, //设置端口号为3001
compress:true, //使用GZIP压缩编译
open:true //设置自动打开浏览器
}
开发环境优化 - HMR模块热替换
- 此功能可有可无,非必须项
- 在已经配置好开发服务器的默认情况下,每次更改代码webpack会把所有页面都打包刷新一次,如果文件多的情况下,会非常耗时间,这时就需要用到HMR模块热替换
- 在devServer配置项里加入hot:true开启HMR功能
- 开启后,修改代码时,只会更新当前修改代码,而不会刷新整个项目
- CSS样式的HMR功能需配置style-loader后才能使用
- Html里HMR功能需要在index.js入口文件entry处加载Html文件
- JS文件默认没有HMR功能,只能处理非入口文件的JS文件
- JS需要在入口文件index.js里写入判断,
if(module.hot){
module.hot.accept('需要HMR功能的JS文件路径'),function (){ //监听如果加载的JS文件发生变化,执行此回调函数 demo(); //具体执行的回调函数 ,回调函数需要在当前JS文件中暴露
}
}
运行(生产)环境优化 - 去除无效代码
- html无需去除无效代码
- CSS,JS、第三方框架和库同样适用去除无效代码
- webpack自带的tree-shaking可以去掉实际上没有使用的JS代码来减少包的大小,必须使用ES6模块化,并开启production运行环境
- 去除无效CSS代码需要npm安装使用purgecss-webpack-plugin插件
- 除在webpack.json.js中顶部引入插件外,还需要再webpack.json.js中配置path方法,可以和const {resolve} = require("path")合并为 const {resolve,join} = require("path")
- 并在plugin处new对应的插件名,写入PATHS方法
- 然后声明PATHS,具体语法如下:
- 示例:
const {resolve,join} = require('path'); //顶部
//顶部和之前的path合并,不影响,都调用的是一个path
const PurgecssWebpackPlugin = require('purgecss-webpack-plugin');
//引入purgecss-webpack-plugin插件
const PATHS = {src:join(__dirname,"src")}
//声明并调用PATHS方法
new PurgecssPlugin(options:{ paths:glob,sync('${PATHS.src}/**/*',{nodir:true})
}), //写paths方法
- 看的比较迷,需要重点去了解
总结
- 如果拿到别人给的项目文件,或者给别人的项目文件
- 没有node_modules和build的情况下
- 只需npm install执行即可恢复,会根据package.json里的配置按顺序执行
- vue-cli脚手架自带webpack相关配置