前言
之前系统的学习了一遍webpack,但一直没有时间好好的整合归纳,在此,将之前学习webpack的笔记以及相关知识点记录在此,相关代码已上传至github
以下是webpack构建的思维导图:
webpack结构
首先我们需要了解webpack构建的一个文件结构
- entry
- output
- loaders
- plugins
- mode
entry
入口文件
modules.exports = {
// 指定打包入口
entry: './src/main.js', // 单入口文件
// 多入口文件
// entry: {
// app: './src/app.js',
// adminApp: './src/adminApp.js'
// }
}
output
打包后的文件存放文章
module.export = {
output : {
filename: '[name].js', // name相当于通配符
path: path.join(__dirname,'dist')
}
}
loaders
主要用于处理webpack不能解析的文件
module.export = {
module: {
/* * 【改动】:loader的使用中,loaders字段变为rules,用来放各种文件的加载器,用rules确实更为贴切 */
rules: [
// 引入css
// npm install --save-dev css-loader style-loader
{
test: /.css$/,
// loader: 'style-loader!css-loader'
use: ['style-loader', 'css-loader'] // 上述格式不正确,加载多个插件,需要用use
},
/* * 【改动】:模板文件的加载方式变化 */ // 模板文件的处理
{
test: /.string$/,
use: { loader: 'html-loader', options: { minimize: true, removeAttributeQuotes: false } }
},
/* * 【改动】:图片文件的加载方式变化,并和字体文件分开处理 */ // 图片的配置
{
test: /.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {/* * 【改动】:图片小于2kb的按base64打包 */ limit: 2048, name: 'resource/[name].[ext]' }
}]
},
/* * 【改动】:字体文件的加载方式变化 */ // 字体图标的配置
{
test: /.(eot|svg|ttf|woff|woff2|otf)$/,
use: [{ loader: 'url-loader', options: { limit: 8192, name: 'resource/[name].[ext]' } }]
},
// 引入对.vue文件的使用
// npm install --save-dev vue-loader vue-template-compiler
{
test: /.vue$/,
loader: 'vue-loader'
}
]
},
}
plugins
主要用于打包优化,资源管理和环境变量的注入
常见的plugin有如下:
| 名称 | 描述 |
|---|---|
| CommonChunksPlugin | 将chunks相同模块代码提取成公共js |
| CleanWebpackPlugin | 清理构建目录 |
| ExtractTextWebpackPlugin | 将css从打包文件里提取成一个独立的css文件 |
| CopyWebpackPlugin | 将文件或文件夹copy到构建的输出目录 |
| HtmlWebpackPlugin | 创建html去承载输出的打包文件 |
| UglifyjsWebpackPlugin | 压缩js |
| ZipWebpackPlugin | 将打包出的资源生成一个zip包 |
常用的loaders及plugin
Scop Hoisting 解决打包代码大量闭包
作用:减少函数声明代码和内存开销
plugins中加入以下配置
// 开启Scop Hosting ,production 环境下默认开启
new webpack.optimize.ModuleConcatenationPlugin(),
SplitChunksPlugin进行公共脚本分离
chunks说明
- async 异步引入的库进行分离(默认)
- initial 同步引入的库进行分离
- all 所有引入的库进行分离(推荐)
详细配置如下:
module.exports = {
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000, // 形成一个新代码块最小的体积,只有 >= minSize 的bundle会被拆分出来
maxSize: 0, //拆分之前最大的数值,默认为0,即不做限制
minChunks: 1, //引入次数,如果为2 那么一个资源最少被引用两次才可以被拆分出来
maxAsyncRequests: 5,// 按需加载的最大并行请求数
maxInitialRequests: 3, // 一个入口最大并行请求数
automaticNameDelimiter: '~', // 文件名的连接符
name: true,
cacheGroups: {
vendors: {
test: /[\/]node_modules[\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
};
html-webpack-externals-plugin优化打包速度
基础库分离
安装 html-webpack-externals-plugin
npm i html-webpack-externals-plugin -D
plugins中配置如下
new HtmlWebpackExternalsPlugin({
externals: [
{
module: 'react',
entry: 'https://11.url.cn/now/lib/16.2.0/react.min.js',
global: 'React'
},
{
module: 'react-dom',
entry: 'https://11.url.cn/now/lib/16.2.0/react-dom.min.js',
global: 'ReactDOM'
}
]
}),
index.html 加入连接
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello Webpack</title>
</head>
<body>
<div id="root"></div>
<!-- react、react-dom提取配置-->
<script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react.min.js"></script>
<script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react-dom.min.js"></script>
</body>
</html>
clean-webpack-plugin(构建时清空dist目录)
安装插件
npm i clean-webpack-plugin -D
配置如下
var { CleanWebpackPlugin} = require('clean-webpack-plugin'); // 语法发生了改变
module.export = {
plugins: [
new CleanWebpackPlugin(), // 打包时先清空dist目录
]
}
px2rem-loader实现移动端适配
安装
npm i px2rem-loader -D
npm i lib-flexible -S
rule配置
{
test: /.less$/,
use: [
'style-loader',
// MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
{
loader:'px2rem-loader',
options : {
remUnit: 75, // 1 rem = 75px
remPrecesion: 8 // px转rem 小数点后面位数
}
}
]
},
index.html中引入lib-flexible
postcss+autoprefixer 实现css3自动补全前缀
安装postcss-loader和autoprefixer
npm i postcss-loader autoprefixer -D
rule配置
{
test: /.less$/,
use: [
'style-loader',
// MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
{
loader : 'postcss-loader',
options : {
plugins: ()=> {
require('autoprefixer')({
browsers: ['last 2 version','>1%','ios 7']
})
}
}
}
]
},
实现多页面打包
安装glob,实现目录页面遍历功能
npm i glob -D
配置如下
const glob = require('glob')
// 获取html-webpack-plugin参数的方法
var getHtmlConfig = function (name, title) {
return {
template: 'index.html', // 指定产出的模板
filename: 'view/' + name + '.html', // 产出的文件名cls
title: title, // 可以给模板设置变量名,在html模板中调用 htmlWebpackPlugin.options.title 可以使用
inject: true,
hash: true,
chunks: ['common', name] // 在产出的HTML文件里引入哪些代码块
};
};
// 获取多入口文件和htmlWebpackPlugin
setMap = () => {
const entry = {};
const htmlwebpackPlugin = []
const entryFiles = glob.sync(path.join(__dirname,'../src/views/common/*/index.js'));
Object.keys(entryFiles).map((index)=>{
const entryFile = entryFiles[index];
const match = entryFile.match(/common/(.*)/index.js/);
const pageName = match && match[1];
htmlwebpackPlugin.push(new HtmlWebpackPlugin(getHtmlConfig(pageName,pageName)));
entry[pageName] = entryFile;
})
return {
entry,
htmlwebpackPlugin
}
}
const {entry,htmlwebpackPlugin} = setMap();
module.exports = {
entry: entry,
output: {
filename: '[name]_[chunkhash:8].js', // name相当于通配符
path: path.join(__dirname, 'dist')
},
plugins: [
].concat(htmlwebpackPlugin),
}
webpack实现SSR(服务器端)打包
服务端渲染 (SSR) 是什么?
渲染: HTML + CSS + JS + Data -> 渲染后的 HTML
服务端:
- 所有模板等资源都存储在服务端
- 内⽹机器拉取数据更快
- ⼀个 HTML 返回所有数据
服务器端渲染&客户端渲染
总结:服务端渲染 (SSR) 的核⼼是减少请求