webpack基本功能和作用我们已经在上一篇文章中进行了详细的描述了,本篇就不再多做说明。下面,让我看看webpack中其它的强大的配置项。
1、css和js的压缩
在平时开发一个项目的时候,我们在项目发布上线的时候,需要对css和js实现压缩,其实在生产环境下css和js会默认进行压缩
压缩的好处:
- 1、减小了文件的体积
- 2、减小了网络传输量和带宽占用
- 3、减小了服务器的处理的压力
- 4、提高了页面的渲染显示的速
下面我们来看看如何配置:
先安装包:
npm i terser-webpack-plugin optimize-css-assets-webpack-plugin -D
配置:
//优化项,里面放着优化的内容
optimization: {
minimize: true, //开启优化项,注意配置在「optimization.minimizer」中的优化项,只会在这个属性为true时才会生效
minimizer: [
//表示放优化的插件
new TerserPlugin({
parallel: true, //开启多进程并行压缩
}),
new OptimizeCssAssetsWebpackPlugin({
assetNameRegExp: /\.css$/g, //指定要压缩模块的正则
//指定压缩css的处理工具
cssProcessor: require("cssnano")({
preset: "default",
}),
}),
],
},
压缩之后的结果:
注意:
- 1、压缩js也可以使用uglifyjs-webpack-plugin这个插件,但是目前这个插件不支持对es6语法的压缩
- 2、如果你使用的是 webpack v5 或以上版本,你不需要安装这个插件。webpack v5 自带最新的 terser-webpack-plugin。
- 如果使用 webpack v4,则必须安装 terser-webpack-plugin v4 的版本。
- 3、要想optimization中的优化插件生效,需要设置minimize 为true
2、将打包后的图片和css打包到指定目录
我们在项目打包的时候可以把打包的css和图片单独放在一个文件夹中去。
安装依赖:
npm i mini-css-extract-plugin file-loader --save-dev
配置图片打包路径:
{
test: /\.(png|jpg|gif)$/,
use: [
{
//url-loader内置了file-loader,会把没有超过设置的大小的静态资源图片,转成base64字符串嵌入到html中去,超过的用file-loader单独打包处理
loader: "url-loader",
options: {
esModule: false, //启用CommonJS模块语法
limit: 20000,
outputPath: "images",//打包图片输出的文件目录
publicPath: "/images",//构建后在html中的路径
},
},
],
},
配置css打包路径:
第一步
//配置插件项
plugins: [
new MiniCssExtractPlugin({
//输入的文件名前面添加路径,那个路径就是打包之后的目录
filename: "css/[name].[contenthash].css",
}),
],
第二步配置规则rule
{
test: /\.scss$/,
//从右向左执行对应的loader,使用MiniCssExtractPlugin.loader替换style-loader
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
3、hash值
hash值一般是结合CDN缓存来使用,通过 webpack构建之后,生成对应文件名自动带上对应的MD5值。如果文件内容改变的话,那么对应文件哈希值也会改变,对应的HML
引用的URL地址也会改变,触发CDN服务器从源服务器上拉取对应数据,进而更新本地缓存
三种hash值:
- 1、hash:和整个项目的构建相关,只要项目文件有修改,塾个项目构建的hash值就会更改
- 2、chunkhash:采用hash计算的话,每次构建后生成的哈希值都不一样,即使文件内容压根没有改变。这样子是没办法实现缓存效果,我们需要换另一种哈希值计算方式,即
chunkhash, chunkhash和hash不一样,它根据不同的入口文件(Entry进行依赖文件解析、构建对应的 Chunk,生成对应的哈希值。我们在生产环境里把一些公共库和程序入口
文件区分开,单独打包构建,接着我们采用chunkhash的方式生成哈希值,只要我们不改动公共库的代码,就可以保证其哈希值不会受影响,就能实现缓存 - 3、contenthash:只要文件的内容不变,生成文件的hash值就不会改变
设置hash值,例如:
new MiniCssExtractPlugin({
//输入的文件名前面添加路径,那个路径就是打包之后的目录
filename: "css/[name].[chunkhash].[contenthash].css",
}),
打包出来的结果,css文件后面会带三个hash值:
4、如何在html中使用图片
webpack处理资源无往不利,但有个问题总是很苦恼,html中直接使用img标签src加载图片的话,因为没有被依赖,图片将不会被打包。这个loader解决这个问题,图片会被打包,而且路径也处理妥当。额外提供html的include子页面功能。
使用html-withimg-loader就可以解决这个问题;
安装:
npm install html-withimg-loader --save-dev
使用:
写在module中
{
test: /\.(html| htm)$/,
use: ["html-withimg-loader"],
},
这样子就可以在html中引入图片了。
如果没有设置这个loader,效果回事这样子的,如下:
如果使用了这个loader,那么图片就能显示出来:
5、处理less和sass
{
test: /\.scss$/,
use: ['style-loader', "css-loader", "less-loader"],
},
{
test: /\.less$/,
use: ['style-loader', "css-loader", "sass-loader"],
},
6、处理css3前缀
为了浏览器浏览器的浏览器的兼容性,有时候我们必须加入-webkit,-ms,-o,-moz这些前缀。
- Triden内核:主要代表为IE浏览器,前缀为-ms
- Gecko内核:主要代表为FireFox,前缀为-moz
- Presto内核:主要代表为Opera,前缀为-o
- Webkit内核:主要代表为Chrome和Safari,前缀为-webkit
我们可以使用postcss-loader和autoprefixer来处理这个问题。
PostCSS的主要功能只有两个:
- 第一个就是把css解析成Javascript可以操作的抽象语法树结构(Abstract Syntax Tree , AST)
- 第二个就是调用插件来处理AST并得到结果
安装:
npm i postcss-loader autoprefixer -D
使用:
{
test: /\.scss$/,
//postcss-loader要在css-loader之前处理
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"sass-loader",
],
}
然后创建postcss.config.js文件,并引入autoprefixer
这样子,打包之后的css例如 ::placeholder就会自动加上前缀
6、使用babel去转义es6,es7,jsx语法
Babel其实是一个变异JavaScript的平台,可以把es6,es7,React的jsx语法转化为es5
安装依赖:
npm i babel-loader @babel/core @babel/preset-env @babel/preset-react -D
npm i @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties -D
@babel/plugin-proposal-class-properties 用来转化处理类的属性 https://babeljs.io/docs/en/babel-plugin-proposal-class-properties
@babel/plugin-proposal-decorators 处理装饰器 https://babeljs.io/docs/en/babel-plugin-proposal-decorators#docsNav
接下来去配置:
webpack.config.js
{
test: /\.js$/,
use: ["babel-loader"],
},
然后在根目录创建一个babel的配置文件.babelrc,就所有的bebel相关的配置都写在这个里面:
{
"presets": [
"@babel/preset-env", //转义es6 es7
"@babel/preset-react" // 转义jsx
],
"plugins": [
["@babel/plugin-proposal-decorators",{"legacy":true}],
["@babel/plugin-proposal-class-properties",{"loose":true}],
]
}
babel-runtime
babel在打包的时候,为了处理es6的一些代码,会自己生成一些工具类函数,但是每一个类都会引入同样的工具函数,但是直接在代码中插入帮助函数,会导致污染了全局环境,并且不同的代码文件中包含重复的代码,导致编译后的代码体积变大,可以使用@babel/runtime来处理这个问题,问题如下:
安装:
npm i @babel/plugin-transform-runtime --save-dev
npm i @babel/runtime --save
配置babel-runtime:
{
"presets": [
"@babel/preset-env", //转义es6 es7
"@babel/preset-react" // 转义jsx
],
"plugins": [
["@babel/plugin-proposal-decorators",{"legacy":true}],
["@babel/plugin-proposal-class-properties",{"loose":true}],
[
"@babel/plugin/transform-runtime",
{
"corejs":true,
"helpers":true,
"regenerator":true,
"useESModule":true
}
]
]
}