示例https://gitee.com/southWindNumber/webpack-demo.git
一、了解webpack原理和概念
- 树结构:在一个入口文件中引入所有资源,形成所有依赖关系树状图
- 模块:模块就是模块,可以是ES6模块也可以是commonJS或者AMD模块,对于webpack来说,所有的资源(css,img)
- chunk打包过程中被操作的模块文件叫做chunk例如异步加载一个模块就是一个chunk
- bundel:bundle是最后打包后的文件,最终文件可以和chunk长的一摸一样,但是大部分情况下他是多个chunk的集合
- 为了优化最后生产出的bundle数量可能不等于chunk的数量,因为有可能多个chunk被组合到了一个Bundle中。
二、webpack安装和体验
- 1、创建项目目录:webpack-demo
- 2、进入目录初始化NPM操作:npm init -y
- 3、安装webpack以及webpack-cli:npm install -g webpack webpack-cli
- 4、创建src目录
- 5、在src下创建一些js文件和一个主入口文件index.js
- 6、控制台运行命令:webpack --mode development(开发环境)
webpack --mode production (生产环境) - 7、可以使用node运行打包后的资源,也可以使用HTML引入打包后的资源
三、webpack的5个核心概念
- 1、entry
- 入口(entry) 指示webpack以哪个文件作为入口起点开始打包,分析构建内部依赖图
- 2、output
- 输出(output)指示webpack打包后的资源bundles输出到哪里,以及如何命名。
-
3、loader
- loader让webpack能够去处理那些非JavaScript资源css、img等,将它们处理成webpack能够识别的资源,也可以理解成一个翻译过程(webpack自身只能理解js和json)。
-
4、plugins
- 插件(plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。
-
5、mode
- 模式(mode)指示webpack使用相应模式的配置。
- 开发模式(development):配置比较简单,能让代码本地调试运行的环境
- 生产环境(production):代码需要不断优化达到性能最好。能让代码优化上线运行的环境。
- 都会自动启用一些插件,生产模式使用插件更多。
四、webpack.config.js核心配置项
webpack配置文件webpack.config.js
作用:指示webpack干那些活,当运行webpack指令时会加载其中配置
构建工具(webpack.config.js)基于node.js平台运行的,模块化默认采用commonjs,而项目文件(src内文件)采用的是ES6语法
开发环境:webpack ./src/index.js -o ./build/build.js --mode development
生产环境: webpack ./src/index.js -o ./build/build.js --mode production
五、多个入口和多个出口的情况–入口文件
1、String:单入口,打包成一个chunk,输出一个bundle文件,chunk的名称为默认。
entry:"./src/index.js"
2、Array:多入口,写多个入口,所有入口文件形成一个chunk(名称默认),输出只有一个bundle,chunk名称默认
entry:["./src/index.js","./src/two.js"]
3、Object:多入口,有几个入口文件就生成几个chunk,并输出几个bundle文件,chunk的名称是key
entry:{
two:"./src/two.js",
index:"./src/index.js"
}
4、特殊用法:
entry:{
//数组中所有入口文件生成一个chunk,输出一个bundle文件,chunk的名称是key
onetwo:["./src/one.js","./src/two.js"],
//形成一个chunk,输出一个bundle文件
index:"./src/index.js"
}
六、webpack打包html资源
- 使用插件(plugins)对HTML文件进行处理(html-webpack-plugin)
- 使用步骤:1、下载 2、引入 3使用
- 下载安装: npm i html-webpack-plugin -D
- 引入插件: const HtmlWebpackPlugin =require(“html-webpack-plugin”);
- 使用插件: plugins:[
//功能:默认会创建一个空的HTML文件,自动引入打包输出的所有资源(js/css)
//new HtmlWebpackPlugin()
//通过参数可以输出有结构的HTML资源
new HtmlWebpackPlugin({
//复制 ‘.src/index.html’文件 并自动引入打包输出的所有资源(js/css)
template:"./src/index.html",
//默认是index.html名称,通过filename设置输出文件名称
//filename:“demo.html”
})
],
html-webpack-plugin插件生成的内存中的页面已帮我们创建并正确引用了打包编译生成的资源(js/css)
七、压缩JS和HTML代码
JS代码只需要设置成生产模式(production) 模式,会自动压缩
压缩HTML方法:
//通过参数可以输出有结构的HTML资源
new HtmlWebpackPlugin({
//复制’./src/demo.html’,并自动引入打包输出的所有资源(js/css)
template:"./src/demo.html",
filename:“demo.html”
//压缩html代码
minify:{
//移除空格
collapseWhitespace:true,
//移除注释
removeComments:true
//不写也行默认生产环境也会去除注释和空格
}
})
八、webpack打包多html开发案例
多html的规律是需要多个entry,每个html一个entry,同时需要新建多个HtmlWebpackPlugin
//多个entry
entry:{
vender:[‘jquery’,’./src/js/common.js’],//公共的
index:"./src/js/index.js",
cart:"./src/js/cart.js"
}
//负责打包html文件 将js注入到html中,minify压缩html
new HtmlWebpackPlugin({
filename:“index.html”,
template:"./src/index.html",
chunks:[“index”,“vendor”],
minify:{
removeComment:true,
collapseWhitespace:true
}
})
new HtmlWebpackPlugin({
filename:“cart.html”,
template:"./src/cart.html",
chunks:[“cart”,“vendor”],//从右到左引入
})
九、webpack打包css资源
需要使用npm下载安装两个loader帮我们完成打包
1、css-loader的作用是处理css中的@import和url这样的外部资源
2、style-loader的作用是把样式插入到DOM中,方法是在header中插入一个style标签,并把样式写入到这个标签的innerHTML里
- npm i css-loader style-loader -D
然后需要在js文件引入css文件,对应的页面对应引入即可实现a是a的样式b是b的
require("../css/style.css")
module: {
rules: [
{
test:/\.css$/,
use:['style-loader','css-loader'],//从右到左执行
}
],
},
过程就是先与js文件绑定,然后在html动态插入style标签
十、webpack打包less或sass资源
- 因为css只是单纯的属性描述,它并不具有变量、条件语句等,css的特性导致了它难组织和维护。
- Sass和Less都属于CSS预处理器,定义了一种新的语言,其基本思想是用一种专门的编程语言,为CSS增加一些编程的特性,将CSS作为目标生成文件,然后开发者使用这种语言进行CSS编码工作
- Less需要使用npm下载less包和less-loader
- Sass需要使用npm下载node-sass包和sass-loader
module: {
rules: [
{
test:/\.css$/,
use:['style-loader','css-loader'],//从右到左执行
},
{
test:/\.less$/,
use:['style-loader','css-loader','less-loader'],//从右到左执行
},
{
test:/\.scss$/,
use:['style-loader','css-loader','sass-loader'],//从右到左执行
}
],
},
十一、提取CSS为单独文件
css内容是打包在js文件中的,可以使用“mini-css-extract-plugin”插件提取成单独的css文件。
1、 在webpack.config.js引入插件
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
2、在plugins模块中使用插件
plugins:[new MiniCssExtractPlugin()],
//或通过参数filename重新命名打包后的css名
plugins:[new MiniCssExtractPlugin({
filename:"./css/demo.css"
})],
3、在css的rules中,使用MiniCssExtractPlugin.loader,取代style-loader,提取js中Css内容为单独文件
{
test:/\.css$/,
use:[MiniCssExtractPlugin.loader,'css-loader'],//从右到左执行
},
如果sass和less也提取成单独css文件,也一样将style-loader换成MiniCssExtractPlugin.loader
{
test:/.css$/,
use:[MiniCssExtractPlugin.loader,‘css-loader’,‘sass-loader’],//从右到左执行
},
十二、处理css的兼容性
- 需要使用postcss处理,下载两个包post-loader和postcss-preset-env
npm i postcss-loader postcss-preset-env -D
- postcss会找到package.json中的browserslist里面的配置,通过配置加载css的兼容性
- 修改loader的配置,新版本需要写postcss.config.js进行配置,less和sass兼容性同理
//从右到左处理,先处理兼容性
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader","postcss-loader"], //从右到左执行
},
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader","postcss-loader"], //从右到左执行
},
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader","postcss-loader"], //从右到左执行
},
],
},
- 配置package.json
"browserslist":[//浏览器兼容
">0.2%",//兼容80%
"last 2 versions",//兼容到最后两个版本
"not dead"//死去的浏览器不需要兼容
]
十三、压缩css
- 使用optimize-css-assets-webpack-plugin插件压缩css内容
- 1、安装
npm i optimize-css-assets-webpack-plugin -D
- 2、引入插件
const OptimizeCssAssetsWebpackPlugin=require("optimize-css-assets-webpack-plugin")
- 3、使用插件
plugins:[new OptimizeCssAssetsWebpackPlugin()]
十四、webpack打包图片资源
- 需下载url-loader和file-loader两个包
- 在css中引入图片
- 在HTML中使用图片 需要下载html-loader
npm i url-loader file-loader -D
//处理html中的图片需要用到
npm i html-loader -D
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: "file-loader",
options: {
publicPath: "../images/", //公共路径
outputPath: "images/", //输出文件夹
limit: 1024 * 8, //限制大小,小于这个的会压缩转化为base64
name: "[name][hash:10].[ext]", //输出的名字 原名字+哈希10位数,加后缀}}
},
},
],
},
{
//处理html中的图片
test: /\.html$/,
loader: "html-loader",
},
十五、webpack打包其他资源
不需要优化和压缩处理,直接输出的资源,称为其他资源
<span class="iconfont"></span>
webpack.config.js
{
//排除css/js/html和图片
exclude:/\.(css|js|html|less|scss|png|gif|jpeg|jpg)$/,
loader:'file-loader',
options:{
name:'[name][hash:10].[ext]',
publicPath:'../font',
outputPath:'font/',
}
}
十六、对js语法配置语法检查eslint
- eslint是一个开源的js代码检查工具,初衷是为了让程序员可以创建自己的检测规则。实际生产中,团队往往会制定一套统一的标准,让整个团队的编码风格达到一致。
- eslint其实与webpack没有任何关系,两者并不互相依赖,甚至一般情况下我们并不会在webpack中进行eslint的配置,可以单独使用。
- 语法检查使用eslint-loader,并基于eslint包,只用来检查js语法。
- 注意只检查自己写的js源代码,第三方库是不用检查的,可以在npmjs.com中查看规则。
- 需要使用js来的规则库来检查代码“airbnb”,需要eslint-config-airbnb-base和eslint-pugin-import两个包
- npm i eslint-loader eslint eslint-config-airbnb-base eslint -plugin -import -D
package.json中加入
"eslintConfig":{
"extends":"airbnb-base"
}
webpack.config.js中加入
{//eslint只检查js语法
test:/\.js$/,
//排除第三方库
exclude:/node_modules/,
loader:'eslint-loader',
options:{//开启自动修复
fix:true,
}
}
在js文件中加入
//下一行eslint所有规则失效
//eslint-disable-next-line
console.log("这是入口文件",11111)
十七、开发服务器devServer配置
npm i webpack-dev-server -D
- devServer给我们提供了开发过程中的服务器,是一个使用了express的Http服务器,它的作用主要是为了监听资源文件的改变,该http服务器和client使用了webpack通信协议,只要资源文件发生改变,webpack-dev-server就会实时的进行编译。
- 只会在内存中编译,不会有任何输出,下载webpack-dev-server包
- webpack-dev-server并不能读取你的webpack.config.js配置的output
- 启动devServer指令为:npx webpack serve 本目录执行
- webpack5无法刷新,解决:添加配置:target:“web”,
webpack.config.js
devServer:{
contentBase:resolve(__dirname,'build'),
//启用gzip压缩
compress:true,
//设置服务器端口号
port:3000,
//自动打开浏览器
open:true
}
package.json
"scripts":{
"test":"echo \"Error: no test specified\"&& exit 1",
"dev":"webpack serve --mode development",
"build":"webpack --mode production"
},
--content-base //设定webpack-dev-server的director根目录,如果不进行设定的话,默认是在当前目录下
--qulet //控制台中不输出打包的信息,开发中一般设置为false,进行打印,这样查看错误比较方便
--no-info //不显示任何信息
--colors//对信息进行颜色输出
--compress //开启gzip压缩
--host <hostname/ip>//设置ip
--port <number>//设置端口号
--inline //webpack-dev-server会在你的webpack.config.js的入口配置文件中再添加一个入口
--hot //开启热替换
--open //自动打开浏览器
--history-api-fallback //查看历史url
十八、环境的优化
开发环境的优化
- 打包构建速度
- 优化代码调试
生产环境的优化
- 代码运行的性能
十九、HMR(模块热替换)
- 模块热替换(Hot Module Replacement 即 HMR)是webpack提供的最有用的功能之一,它允许在运行时更新各种模块,而无需进行完全刷新。
- 启用这个功能,只需要修改一下webpack.config.js的配置,使用webpack内置的HMR插件就可以了,在devServer中使用hot参数。
- 启用webpack内置的HMR插件后,module.hot接口就会暴露在index.js中,接下来需要在index.js中配置告诉webpack接收HMR的模块。
- 1.样式HMR功能,默认也没有HMR功能,只能处理非入口文件的js文件。
- 2.HTML的HMR功能,默认没有HMR功能(不用做HMR功能),需要在entry入口中引入html文件。
- 3.js的HMR功能,默认没有HMR功能,只能处理非入口文件的js文件。
- 启用webpack内置的HMR插件后,module.hot接口就会暴露在index.js中,接下来需要在index.js中配置告诉webpack接受HMR的模块
if(module.hot){
module.hot.accept('./print.js',function(){
//告诉webpack接受热替换的模块
console.log('Accepting the updated printMe module')
printMe();
})
}
服务器检测到了print.js的代码变化执行了module.hot.accept的回调函数
二十、去除项目里的死代码
-
去除没有用到的JS代码
- webpack通过tree-shaking去掉了实际上并没有使用的js代码来减少包的大小。
- 1、必须使用es6模块化,2、开启production环境
-
去除没有用到的css
- 比如我们经常使用的BootStrap(140kb)就可以减少到只有35kb大小
- webpack使用purgecss-webpack-plugin去除无用的css
const {resolve,join} = require('path');
const PurgecssPlugin = require('purgecss-webpack-plugin');
const glob = require('glob');
const PATHS = {src:join(__dirname,'src')}
new PurgecssPlugin({
paths:glob.sync(`${PATHS.src}/**/*`,{nodir:true})
})