webpack工具学习loader的后续和插件(二)
前面我们知道webpack中loader是转化js之外的文件工具,那我们就来认知一下常用的loader
1. less-loader
工具处理less文件
image.pngless文件
image.pngjs文件
1.配置项目文件
npm init -y
- 安装webpack
sudo npm install --save-dev webpack
npm install --save-dev webpack-cli
3.安装less-loader
sudo npm install --save-dev less
安装less
npm install --save-dev less-loader
安装less转化工具
sudo npm install --save-dev css-loader
安装css转化工具
npm install style-loader --save-dev
安装style-loader
4.配置
webpack.config.js
文件
const path = require("path");
module.exports = {
devtool: "cheap-module-eval-source-map",
mode: "development",
entry: "./index.js",
output: {
/*
filename: 指定打包之后的JS文件的名称
* */
filename: "bundle.js",
/*
path: 指定打包之后的文件存储到什么地方
* */
path: path.resolve(__dirname, "bundle")
},
module: {
rules:[
{
test:/\.less$/,
use: [{
//将css代码放到 head中
loader: "style-loader" // creates style nodes from JS strings
}, {
//将css转化模块代码
loader: "css-loader" // translates CSS into CommonJS
}, {
//将less转为css代码
loader: "less-loader" // compiles Less to CSS
}]
}
]
}
};
5.打包
npx webpack
后续的 打包scss文件 和这个流程一样
安装scss
sudo npm install sass-loader node-sass webpack --save-dev
这个命令行其实 安装2个 一个是sass,sass-loader
postcss-loader
转化工具
首先说明一下PostCSS是什么?
PostCSS是一款使用插件去转换CSS的工具,比如:autoprefixer(自动补全浏览器前缀),postcss-pxtorem(自动把px代为转换成rem)
安装postcss-loader加载器
npm i -D postcss-loader
安装postcss-loader
npm i -D autoprefixer
安装插件
image.png3.在webpack.config中配置
postcss-loader
,在css-loader or less-loader or sass-loader之前添加postcss-loader
用到那个 css的loader就在其后面加载
4.创建
postcss.config.js
配置文件
module.exports = {
plugins: {
"autoprefixer": {
"overrideBrowserslist": [
"ie >= 8", // 兼容IE7以上浏览器
"Firefox >= 3.5", // 兼容火狐版本号大于3.5浏览器
"chrome >= 35", // 兼容谷歌版本号大于35浏览器,
"opera >= 11.5" // 兼容欧朋版本号大于11.5浏览器,
]
}
}
};
image.png
2. Plugin 插件
- plugin插件就是用来扩展webpack的功能,当然
loader
也是扩展了webpack的功能 ,但是它只专注于转化文件
这一个领域。
我们之前在说
loader
的时候,每次打包转化后的文件,必须将index.html
复制一份到bundle
目录下才可以运行,Plugin
中的插件就可以解决上述的一个问题
2.1 HtmlWebpackPlugin
插件
- HtmlWebpackPlugin会在打包结束之后
自动创建一个index.html
, 并将打包好的JS自动引入到这个文件中 - 默认情况下
HtmlWebpackPlugin
生成的index.html文件是一个空的文件
- 如果想指定原来的index.html,在创建
HtmlWebpackPlugin
对象的时候,需要做如下配置
new HtmlWebpackPlugin({
//指定原来的模板对象
template: "index.html",
minify: {
//生成的html的压缩文件
collapseWhitespace: true
}
})
npm install --save-dev html-webpack-plugin
安装 HtmlWebpackPlugin
2.在
webpack.config.js
中配置
//导入path模块
const path = require("path");
//导入 插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
/*
配置sourcemap
development: cheap-module-eval-source-map
production: cheap-module-source-map
* */
devtool: "cheap-module-eval-source-map",
/*
mode: 指定打包的模式, 模式有两种
一种是开发模式(development): 不会对打包的JS代码进行压缩
还有一种就是上线(生产)模式(production): 会对打包的JS代码进行压缩
* */
mode: "development", // "production" | "development"
/*
entry: 指定需要打包的文件
* */
entry: "./index.js",
/*
output: 指定打包之后的文件输出的路径和输出的文件名称
* */
output: {
/*
filename: 指定打包之后的JS文件的名称
* */
filename: "bundle.js",
/*
path: 指定打包之后的文件存储到什么地方
* */
path: path.resolve(__dirname, "bundle")
},
/*
module: 告诉webpack如何处理webpack不能够识别的文件
* */
module: {
rules: [
// 打包字体图标规则
{
test: /\.(eot|json|svg|ttf|woff|woff2)$/,
use: [
{
loader: 'file-loader',
options: {
// 指定打包后文件名称
name: '[name].[ext]',
// 指定打包后文件存放目录
outputPath: 'font/',
}
}
]
},
// 打包图片规则
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
// 指定图片限制的大小
limit: 1024 * 100,
// 指定打包后文件名称
name: '[name].[ext]',
// 指定打包后文件存放目录
outputPath: 'images/',
}
}
]
},
// 打包CSS规则
{
test: /\.css$/,
// use: [ 'style-loader', 'css-loader' ]
use:[
{
loader: "style-loader"
},
{
loader: "css-loader",
options: {
// modules: true // 开启CSS模块化
}
},
{
loader: "postcss-loader"
}
]
},
// 打包LESS规则
{
test: /\.less$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "less-loader"
},{
loader: "postcss-loader"
}]
},
// 打包SCSS规则
{
test: /\.scss$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "sass-loader"
},{
loader: "postcss-loader"
}]
},
]
},
/*
plugins: 告诉webpack需要新增一些什么样的功能
* */
plugins: [new HtmlWebpackPlugin({
// 指定打包的模板, 如果不指定会自动生成一个空的
template: "./index.html",
minify: {
// 告诉htmlplugin打包之后的html文件需要压缩
collapseWhitespace: true,
}
})]
};
npx webpack
打包 项目文件
2.2 css-plugin
插件
- 就是把css代码单独打包一个.css文件中
-
mini-css-extract-plugin
是一个专门用于将打包的CSS内容提取到单独文件的插件
npm install --save-dev mini-css-extract-plugin
安装
2.在webpack.config中配置
mini-css-extract-plugin
2.1导入
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
//在 plugin中添加插件
new MiniCssExtractPlugin({
filename: './css/[name].css',
})
image.png2.2 替换style-loader
loader: MiniCssExtractPlugin.loader,
通过
mini-css-extract-plugin
打包出来的css代码是没有压缩的,如果想要压缩,需要另外一个插件optimize-css-assets-webpack-plugin
压缩css,terser-webpack-plugin
压缩js
npm install --save-dev optimize-css-assets-webpack-plugin
安装插件
npm install --save-dev terser-webpack-plugin
安装压缩js插件
2,引入和配置插件
//导入插件
const TerserJSPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// 配置webpack优化项 module.exports
optimization: {
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
}
image.png
2.3 webpack.config中的 watch和devServer配置
我们在开发阶段,需要不断的编写代码和编译,不能编写一次代码就打包一次 运行看结果,这样很是浪费,所以就需要
webpack.config
中添加一些配置,watch
和devServer
他们的作用都是监听打包文件变化,当它们修改后会重新编译打包
module.exports = {
//告诉webpack重新编译
watch: true,
watchOptions: {
aggregateTimeout: 300, // 防抖, 和函数防抖一样, 改变过程中不重新打包, 只有改变完成指定时间后才打包
poll: 1000, // 每隔多少时间检查一次变动
ignored: /node_modules/ // 排除一些巨大的文件夹, 不需要监控的文件夹
},
}
-
devServer
的配置 和watch
有所不同
webpack-dev-server
可以将我们打包好的程序运行在一个服务器环境下,还可以解决企业开发中"开发阶段"的跨域问题
1、
npm install webpack-dev-server --save-dev
安装
2.在
webpack.config配置
module.exports = {
devServer: {
contentBase: "./bundle", // 打包后的目录
open: true, // 是否自动在浏览器中打开
port: 3030 // 服务器端口号
},
proxy: [{
context: ["/user", "/login"],
target: "http://127.0.0.1:3000",
changeOrigin: true, // 域名跨域
secure: false, // https跨域
// pathRewrite:{"": "/xxx"} // 路径重写, 将路径中的xxx替换为空
}],
}
注意: 通过
webpack-dev-server
自动打包生成的bundle.js文件
并没有真正的放到物理磁盘中,而是放在内存中,这样不会影响网页的性能
缺点:
通过webpack-dev-server
可以实现实时监听打包内容的变化,每次打包之后都会自动刷新网页,那么通过JS
动态添加的元素,在网页刷新的时候就会消失,为了解决这个问题,需要在devServer
中开启热更新
,热更新插件, 会在内容发生改变的时候时时的更新修改的内容但是不会重新刷新网站
2.4 HMR(HotModuleReplacementPlugin) 热更新插件的使用
HotModuleReplacementPlugin
是一个内置插件, 所以不需要任何安装直接引入webpack模块即可使用
- 在
devServer
中开启热更新
hot: true
, 开启热更新
hotOnly: true
即使热更新不生效,浏览器也不自动刷新
3.在
webpack.config.js
中创建热更新插件new Webpack.HotModuleReplacementPlugin()
需要注意的是:
- 如果是通过
style-loader
来处理CSS, 那么经过前面两步就已经实现了热更新- 如果是通过
MiniCssExtractPlugin.loader
来处理CSS, 那么还需要额外配置MiniCssExtractPlugin.loader
options:{ hmr: true }
const path = require("path");
//引入webpcak 创建热更新插件
const Webpack = require("webpack");
module.exports = {
/*
devServer: 自动检测文件变化配置
* */
devServer: {
contentBase: "./bundle",
open: true,
port: 9090,
proxy: [{
context: ["/user", "/login"],
target: "http://127.0.0.1:3000",
changeOrigin: true, // 域名跨域
secure: false, // https跨域
}],
hot: true, // 开启热更新, 只要开启了热更新就不会自动刷新网页了
hotOnly: true // 哪怕不支持热更新也不要刷新网页
},
devtool: "cheap-module-eval-source-map",
mode: "development", // "production" | "development"
entry: "./src/js/index.js",
output: {
filename: "js/bundle.js",
path: path.resolve(__dirname, "bundle")
},
/*
module: 告诉webpack如何处理webpack不能够识别的文件
* */
module: {
rules: [
// 打包CSS规则
{
test: /\.css$/,
use:[
{
// loader: "style-loader"
//如果使用MiniCssExtractPlugin.loader,在使用热更新的时候,就需要 配置 options
loader: MiniCssExtractPlugin.loader,
options:{
hmr: true
}
},
// 如果是 css-loade,系统会自动处理热更新
{
loader: "css-loader",
options: {
// modules: true // 开启CSS模块化
}
},
]
},
]
},
/*
plugins: 告诉webpack需要新增一些什么样的功能
* */
plugins: [
//创建热更新插件
new Webpack.HotModuleReplacementPlugin()
]
};
需要注意第二点是: 对于
css模块而言
, 在css-loade
r中已经帮我们实现了热更新, 只要css代码被修改就会立即更新
,但是对于JS模块
,系统默认并没有实现热更新,需要开发人员手动实现
// 判断是否开启热更新
if(module.hot){
// 监听指定那个JS模块变化
// 比如:xxxx.js
module.hot.accept("./xxxx.js", function () {
// 这里实现 要热更新的代码
});
}
3.Babel官网
作用: 我们在开发过程中,可能使用ES6/7/8语言,但是在低级版本浏览器中,可能 不识别ES6/7/8,所以
Babel
插件,就是可以帮助我们把ES678高级语法转换为ES5低级语法
npm install --save-dev babel-loader @babel/core
安装babel-loader
和@babel/core
的核心库
2.
npm install @babel/preset-env --save-dev
安装 preset-env插件,把高级JS语法转化了 ES2015+
注意:
es678
中的语法中,有的可能是在ES5
中没有对应关系,也就是es678
新增的一些语法,那么在转化的时候就需要 安装polyfill
包
3.
npm install --save @babel/polyfill
安装polyfill
包
npm install --save-dev @babel/plugin-transform-runtime
安装plugin-transform-runtime
npm install --save @babel/runtime
安装@babel/runtime
4.配置文件 在
module
节点下的rules
数组中,添加一个新的匹配规则``
exclude
是排除node_modules文件目录
{
text:/\.js/,
loader:"babel-loader",
exclude:/node_modules/,
options:{
"presets": ["@babel/preset-env",{
targets: {
//告诉babel 需要兼容哪些浏览器
"chrome": "58",
"ie": "10"
},
//只打包我用的 js语法 没有用到的 不打包
useBuiltIns: "usage",
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"absoluteRuntime": false,
"corejs": 2,
"helpers": true,
"regenerator": true,
"useESModules": false
}
]
]
}]
}
}
注意点:
"corejs": false
, 还是全局注入,还是会污染全局环境
"corejs": 2
, 则不会污染全局环境需要安装@babel/runtime-corejs2
npm install --save @babel/runtime-corejs2
3.图片的处理
我们知道
file-loader
和url-loader
可以将HS或者css中用到的图片打包到指定的目录,但是他们2个不可以打包html
代码中的用到的图片,还有一般图片可能可有几kb/100多kb
,有时还需要压缩,甚至也需要自己合并图片,比如自己合并精灵图
所以就需要下面一些loader
工具
1.打包
html
代码html-withimg-loader
github官网地址
npm install html-withimg-loader --save
需要如下规则
{
test: /\.(htm|html)$/i,
loader: 'html-withimg-loader'
}
2.图片压缩loader,可以处理
png/jpg/jpeg/gif/svg/werp
等
npm install image-webpack-loader --save-dev
安装image-webpack-loader
配置
rules: [{
test: /\.(gif|png|jpe?g|svg)$/I,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 65
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false,
},
pngquant: {
quality: [0.65, 0.90],
speed: 4
},
gifsicle: {
interlaced: false,
},
// the webp option will enable WEBP
webp: {
quality: 75
}
}
},
],
}]
- 图片的合并,
postcss
这个工具里面有一个插件postcss-sprites
用来合并图片成精灵图
npm install --save -d postcss-sprites postcss
安装postcss-sprites 和postcss
配置 新建
postcss.congif.js
文件
module.exports = {
plugins: {
//自动补全前缀插件
"autoprefixer": {
"overrideBrowserslist": [
"ie >= 8", // 兼容IE7以上浏览器
"Firefox >= 3.5", // 兼容火狐版本号大于3.5浏览器
"chrome >= 35", // 兼容谷歌版本号大于35浏览器,
"opera >= 11.5" // 兼容欧朋版本号大于11.5浏览器,
]
},
// "postcss-pxtorem": {
// rootValue: 100, // 根元素字体大小
// // propList: ['*'] // 可以从px更改到rem的属性
// propList: ["height"]
// }
//图片合并插件
"postcss-sprites": {
// 告诉webpack合并之后的图片保存到什么地方
spritePath: "./bundle/images",
// 告诉webpack合并图片的时候如何分组
groupBy: function (image) {
// url: '../images/animal/animal1.png',
let path = image.url.substr(0, image.url.lastIndexOf("/"));
// console.log(path, "!!!!!!");
let name = path.substr(path.lastIndexOf("/") + 1);
// console.log(name, "!!!!!!!!");
return Promise.resolve(name);
},
//告诉插件 哪些图片不需要合并
filterBy: function (image) {
let path = image.url;
if(!/\.png$/.test(path)){
return Promise.reject();
}
return Promise.resolve();
}
}
}
};
注意:在使用
loader
处理图片时,有可能会打包完整之后,图片并没有完整的显示,原因是路径可能是错误的
, 需要在url-loader
图片处理规则中,配置options
的publicPath
属性,指定服务图片的地址
4. ESlint
-ESLint
是一个插件化的javascript
代码检测工具,可以检查常见的JS
错误,也可以惊醒代码规范
- 安装
pm install eslint-loader --save-dev
loader工具
npm install eslint --save-dev
安装ESLint
2.在
webpack.config.js
中配置module
中的rules
规则
module: {
rules: [
// 检查编码规范的规则
{
// enforce: "pre"作用: 让当前的loader再其它loader之前执行
enforce: "pre",
test: /\.js$/,
//过滤掉那个目录
exclude: /node_modules/,
//包含那个目录
include: path.resolve(__dirname, "index.js"),
loader: 'eslint-loader',
options: {
// eslint options (if necessary)
//自动修复错误
fix: true
},
}
]
}
3.配置
.eslintrc.js
文件
module.exports = {
/*
不重要,永远写true
* */
root: true,
parserOptions: {
// parser: 'babel-eslint',
/*
默认设置为 3,5(默认), 你可以使用 6、7、8、9 或 10 来指定你想要使用的 ECMAScript 版本
* */
"ecmaVersion": 10,
/*
设置为 "script" (默认) 或 "module"(如果你的代码是 ECMAScript 模块)。
* */
"sourceType": "module",
/*
ecmaFeatures - 这是个对象,表示你想使用的额外的语言特性:
globalReturn - 允许在全局作用域下使用 return 语句
impliedStrict - 启用全局 strict mode (如果 ecmaVersion 是 5 或更高)
jsx - 启用 JSX
* */
"ecmaFeatures": {}
},
// 指定代码运行的宿主环境
env: {
browser: true, // 浏览器
node: true, // node
/*
支持 ES6 语法并不意味着同时支持新的 ES6 全局变量或类型(比如 Set 等新类型)。
对于 ES6 语法,使用 { "parserOptions": { "ecmaVersion": 6 } }
* */
es6: true,
},
extends: [
/*
引入standard代码规范
* */
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
'standard'
],
/*
扩展或覆盖规则
* */
rules: {
// 强制语句结束添加,分号
semi: ["error", "always"],
// 强制缩进2个空格
indent: ["error", 4],
// 方法名和刮号之间不加空格
'space-before-function-paren': ['error', 'never'],
"no-unexpected-multiline": "off"
}
};
5.配置webpack.config.js
文件的优化
5.1提取webpack.config.js
公用部分
我们知道不同的环境配置文件不太一样,比如开发环境和上线环境 就是要区别开的,所以就需要我们,提取出共通的配置文件,比如: 文件入口
entry
,打包输入的路径配置output
,CSS的处理等。 这么久需要用到webpack-merge
插件配置
npm install --save-d webpack-merge
安装
比如提取的公用配置文件
webpack.config.common.js
,开发环境的为webpack.config.dev.js
,生产环境的是webpack.config.pro.js
,那么假设在开发环境中使用时,就需要在webpack.config.dev.js
做如下配置
//打包的时候生成一个index.ml文件
const Webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
//引入公用的配置文件
const CommonConfig = require("./webpack.config.common.js");
//引入webpack-merge配置插件
const Merge = require("webpack-merge");
//配置文件
const DevConfig = {
/*
devServer: 自动检测文件变化配置
* */
devServer: {
contentBase: './bundle',
open: true,
port: 9090,
proxy: [{
context: ['/user', '/login'],
target: 'http://127.0.0.1:3000',
changeOrigin: true, // 域名跨域
secure: false, // https跨域
pathRewrite: { '': '/api' } // 路径重写, 将路径中的api替换为空
}],
hot: true, // 开启热更新, 只要开启了热更新就不会自动刷新网页了
hotOnly: true // 哪怕不支持热更新也不要刷新网页
},
/*
配置sourcemap
development: cheap-module-eval-source-map
production: cheap-module-source-map
* */
devtool: 'cheap-module-eval-source-map',
/*
mode: 指定打包的模式, 模式有两种
一种是开发模式(development): 不会对打包的JS代码进行压缩
还有一种就是上线(生产)模式(production): 会对打包的JS代码进行压缩
* */
mode: 'development', // "production" | "development"
/*
plugins: 告诉webpack需要新增一些什么样的功能
* */
plugins: [
new HtmlWebpackPlugin({
// 指定打包的模板, 如果不指定会自动生成一个空的
template: './src/index.html',
}),
new Webpack.HotModuleReplacementPlugin()
]
};
//Merge 配置
module.exports = Merge(CommonConfig, DevConfig);
更改
package.json
里面的脚本命令
"scripts": {
"start": "npx webpack-dev-server --config webpack.config.dev.js",
"dev": "npx webpack --config webpack.config.dev.js",
"prod": "npx webpack --config webpack.config.prod.js"
},
5.2代码优化分割
所谓的代码分割就是: 打包在多次打包的时候,打开网页需要都需要下载新的打包文件,这样会消耗性能,就需要把一些没有更改的文件在第一次打开网页的时候,缓存下来,那么在修改其他文件之后,在打包的时候,只需要下载新修改的文件即可。需要在
webpack.config.js
文件中添加一下配置
optimization: {
splitChunks: {
chunks: "all"
}
},
5.3 异步加载代码 和 Prefetching
有些模块需要用到的时候再去加载,
懒加载
Prefetching
:空闲的时候加载,也就是等当前被使用的模块都加载完空闲下来的时候就去加载, 不用等到用户用到时再加载,这样防止资源过大,等用户用的时候加载过慢
const oBtn = document.querySelector('button');
oBtn.onclick = function() {
getComponment().then(($div) => {
document.body.appendChild($div[0]);
});
};
//方式一
function getComponment() {
// 返回的事promise函数
return import('jquery').then(({ default: $ }) => {
const $div = $('<div>我是div</div>');
return $div;
});
}
//方式二 async函数实现
async function getComponment() {
//Prefetching 魔法注释加载
const { default: $ } = await import(/* webpackPrefetch: true *//* webpackChunkName: "jquery" */'jquery');
const $div = $('<div>我是div</div>');
return $div;
}
5.4浏览器缓存问题
浏览器有一个特点就是自动缓存网页上的资源, 以便于提升下次访问的速度,但正式因为浏览器的缓存机制, 导致文件内容被修改之后只要文件名称没有发生变化,就不会重新去加载修改之后的资源, 所以刷新网页后显示的还是修改之前的内容
为了解决上面的问题,我们就需要在打包文件的时候给
文件名称加上内容的hash值
,一旦内发生变化, 内容的hash值就会发生变化, 文件的名称也会发生变化,这样浏览器就会去加载
注意:
webpack4.0
以后一般使用contenthash
哈希值,它是根据某个文件内容生成的哈希值, 只要某个文件内容发生改变,该文件的contenthash
就会发生变化,一般使用在正式环境 打包上线
,
如何加载设置
contenthash
哈希值?
我们只需要在webpack.config.js
,转化的资源名称后面添加[contenthash:8]
,其中8是哈希值的长度,通常是 输出的资源,比如:js
,图片
,字体图标
output: {
/*
filename: 指定打包之后的JS文件的名称
contenthash 添加哈希值
* */
filename: 'js/[name].[contenthash:8].js',
/*
path: 指定打包之后的文件存储到什么地方
* */
path: path.resolve(__dirname, 'bundle')
},
image.png
5.5模块的全局导入
我们用过
npm
安装的模块,只能通过import
导入模块使用,如果一个模块在每个文件中都需要引入,那这样是需要在每一个文件中都需要import
导入的,为了解决这个问题,一次设置全局使用,就需要用到Provide-Plugin
插件
Provide-Plugin
插件 是系统自带的,不需要安装,只要引入webpack
,创建插件就可以
//引入插件
const Webpack = require("webpack");
module.exports = {
/*
plugins: 告诉webpack需要新增一些什么样的功能
* */
plugins: [
new CleanWebpackPlugin(),
new CopyWebpackPlugin([{
from: './doc',
to: 'doc'
}]),
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css'
}),
//设置jquery是全局导入,只需要使用$就可以
new Webpack.ProvidePlugin({
$: 'jquery'
})
]
}
5.6 resolve解析规则
-
resolve
用于配置导入模块
的解析规则
我们在项目开发的过程中,有时候需要导入很多模块,那么在写导入模块的路径,可能是很长,为了简化导入的代码,就需要用到
resolve
,导入模块
的解析规则
比如我们在
js
文件中 导入一个import 'bootstrap/dist/css/bootstrap.css'
css文件,可以通过resolve
规则简化,需要在webpack.config.js
做一些配置
第一种:那就是通过resolve的alias,
起别名
,然后直接import $ from 'bootstrap';
导入这个模块即可
module.exports = {
resolve: {
alias: {
// 创建 import 或 require 的别名,来确保模块引入变得更简单
bootstrapcss: 'bootstrap/dist/css/bootstrap.css'
}
},
}
第二种就是通过 修改入口查找顺序,简化导入代码
module.exports = {
resolve: {
// alias: {
// // 创建 import 或 require 的别名,来确保模块引入变得更简单
// bootstrapcss: 'bootstrap/dist/css/bootstrap.css'
// }
// 指定模块入口的查找顺序 的第一种情况
// mainFields: ['style', 'main']
// 指定导入模块查找顺序的第二种情况
extensions: ['.css', '.js', '.joson'],
// 指定查找范围, 告诉webpack只在node_modules中查找
modules: ["node_modules"]
}
}
5.7 Module中 noParse
提升打包速度
我们知道一些第三方库,会有依赖关系,我们在导入模块库的时候,
webpack
都会分析这个库是否有依赖关系,但是对于一些独立模块
是没有依赖关系的,就不需要在webpack
在分析,所以需要使用noParse
在Module
中指出,这样可以提升我们的打包速度
module.exports = {
//告诉webpack如何处理webpack不能够识别的文件,如何转化
module: {
//告诉webpack不需要处理分析jquery,因为他是一个独立的第三方库
noParse: /jquery/,
}
}
5.8 IgnorePlugin
内置插件,忽略指定的目录
-
IgnorePlugin
是webpack
的一个内置插件 - 用于忽略第三方包指定目录,让指定目录不被打包进去
const Webpack = require('webpack');
module.exports = {
/*
plugins: 告诉webpack需要新增一些什么样的功能
* */
plugins: [
/*
以下代码的含义:
在打包moment这个库的时候, 将整个locale目录都忽略掉
moment.js是一个处理日期的 第三方库
* */
new Webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
]
}
5.9dll动态链接库
-
dll
动态链接库用于防止重复打包不会发生变化的第三方模块
,来提升webpack
的打包效率
实现步凑1 : 创建一个配置文件
webpack.config.dll.js
,来打包不会发生变化的第三方库
//引入path模块
const path = require('path');
//引入webpack
const Webpakc = require('webpack');
//配置文件
module.exports = {
//打包模式
mode: 'production',
//指定打包的入口文件
entry: {
vendors: ['jquery', 'lodash']
},
// output: 指定打包之后的文件输出的路径和输出的文件名称
output: {
//name是入口的 对应的key 就是 vendors
filename: '[name].dll.js',
path: path.resolve(__dirname, 'dll'),
library: '[name]'
},
//添加插件
plugins:[
/*
DllPlugin作用:
在打包第三方库的时候生成一个清单文件
* */
new Webpakc.DllPlugin({
name: '[name]',
path: path.resolve(__dirname, 'dll/[name].manifest.json')
})
]
};
- 使用
add-asset-html-webpack-plugin
插件,把打包的不变的第三方库,插入到html文件
中使用
注意
:add-asset-html-webpack-plugin
插件是HtmlWebpackPlugin
插件的扩展,需要在HtmlWebpackPlugin后创建
2.1 我们在
webpack.config.dll.js
文件中配置了打包清单
,需要在webpack.config.common.js
的配置文件中告诉webapck
在打包的时候,不需要在打包清单中的文件
const path = require('path');
const Webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
// 指定打包的模板, 如果不指定会自动生成一个空的
template: './src/index.html'
}),
new AddAssetHtmlPlugin({
//使用这个插件,把路径的中的vendors.dll.js文件,插入到html中
filepath: path.resolve(__dirname, 'dll/vendors.dll.js')
}),
new Webpack.DllReferencePlugin({
// 告诉webpack清单的文件,不需要在打包
manifest: path.resolve(__dirname, 'dll/vendors.manifest.json')
})
]
}
- 需要在
package.json
文件中,添加脚本script编译
,收到打包一次
"scripts": {
"start": "npx webpack-dev-server --config webpack.config.dev.js",
"dev": "npx webpack --config webpack.config.dev.js",
"prod": "npx webpack --config webpack.config.prod.js",
"dll": "npx webpack --config webpack.config.dll.js"
},
注意上面的
webpack.config.dll.js
文件中,我们把jquery
,lodash
打包合成了一个vendors .dll.js
文件,但是有时在开发工程的时候,不需要这样,希望单独的打包成独立的文件,那么就如下做法,entry
对应的文件单独分离
开来
const path = require('path');
const Webpack = require('webpack');
module.exports = {
mode: 'production',
entry: {
jquery: ['jquery'],
lodash: ['lodash'],
},
output: {
filename: '[name].dll.js',
path: path.resolve(__dirname, 'dll'),
library: '[name]'
},
plugins:[
/*
DllPlugin作用:
在打包第三方库的时候生成一个清单文件
* */
new Webpack.DllPlugin({
name: '[name]', // 注意这个名称必须和library名称一致
path: path.resolve(__dirname, 'dll/[name].manifest.json')
})
]
};
image.png
那么在对应的
webpack.config.commoc.js
文件中,要动态的生成 AddAssetHtmlPlugin对应的路径
const path = require('path');
const Webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
const fs = require('fs');
const plugins = [
new HtmlWebpackPlugin({
// 指定打包的模板, 如果不指定会自动生成一个空的
template: './src/index.html'
})
];
//动态生成路径
const dllPath = path.resolve(__dirname, 'dll');
const files = fs.readdirSync(dllPath);
files.forEach(function (file) {
if(file.endsWith(".js")){
plugins.push(new AddAssetHtmlPlugin({
filepath: path.resolve(__dirname, 'dll', file)
}));
}else if(file.endsWith(".json")){
plugins.push(new Webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, 'dll', file)
}));
}
});
module.exports = {
//配置插件
plugins: plugins
}