本质上,webpack是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle。
安装webpack:npm i webpack@4.26.1 webpack-cli@3.1.2 -D
npm是一个包管理工具,可以通过npm下载使用各种包(代码模块)。它是通过NodeJS编写的,所以要使用npm,必须要安装NodeJS。安装Node的时候,会自动安装npm。
常用包:clean-webpack-plugin@1.0.0 css-loader@2.0.0 file-loader@2.0.0 html-webpack-plugin@3.2.0 style-loader@0.23.1 url-loader@1.1.2npm
要注意不同版本的webpack API可能不一样,平常用自己最熟悉的就好了,没必要进行升级。
webpack -h 查看所有webpack命令
核心概念:
- 入口(entry):进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。每个依赖项随即被处理,最后输出到称之为bundles的文件中。可以有多个入口文件。
- 如果不是用默认的index.js作为默认入口文件,就需要自己配置入口和出口文件。
- 出口(output):output 属性告诉 webpack 在哪里输出它所创建的bundles,以及如何命名这些文件,默认值为
./dist。
filename用于输出文件的文件名。path为输出目录的绝对路径。- 如果配置了多个入口,就需要占位符来配置不同的名称
filename: '[name].bundle.js'
- loader:loader让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。
test属性,阐明需要进行转换的文件。use属性,表示进行转换时,应该使用哪个 loader。
-
插件(plugins):loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。
想要使用一个插件,你只需要
require()它,然后把它添加到plugins数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用new操作符来创建它的一个实例。 -
模式(mode):
- production生产模式:会将生成的代码进行压缩
- development开发模式:不会被压缩
- none:不会被压缩
配置文件
package.json:定义了项目所需的各种模块,以及项目的配置信息,npm install会根据这个配置文件,自动下载所需的模块,也就是配置项目所需的运行和开发环境。是管理本地npm包的最佳方式。
npm init命令会自动生成这个文件
属性说明:
- name:项目名称
- scripts:指定了运行脚本命令的npm命令行缩写,比如
"build": "webpack --mode production",通过npm run build可以运行webpack
参考文章:javascript.ruanyifeng.com/nodejs/pack…
webpack.config.js:webpack配置文件
// path路径是node提供的,需要引入
var path = require('path');var HtmlWebpackPlugin = require('html-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = { // 入口文件 entry: { app: './src/app.js' }, output: { // 设置出口文件路径,__dirname代表根目录 path: path.resolve(__dirname, 'dist'), // 设置出口文件名称 filename: '[name].bundle.js' },
// 处理第三方文件 module: { rules: [{ // 用babel-loader处理以js为后缀的文件 test: /\.js$/, use: 'babel-loader', // 排除node_modules里的js文件,提高打包效率 exclude: /(node_modules)/ }] } plugins: [ new HtmlWebpackPlugin({ template: "./index.html", filename: "app.html", chunks: ['app'], // 将js文件插入到body标签里面 inject: "body" }), new CleanWebpackPlugin(['dist']) ]}
然后在经过npm run build编译
入口文件设置的其他写法:
有多个入口文件可以用下面这两种写法
-
键值对
module.exports = { // 入口文件 entry: { app: './src/app.js', new: './src/new.js' }, output: { // 设置出口文件路径,__dirname代表的是当前文件的绝对路径 path: path.resolve(__dirname, 'dist'), // 设置出口文件名称 filename: '[name].bundle.js' } }
-
数组表示
entry: ['./src/app.js']
模块化
webpack支持三种模块化:AMD(RequireJS)、ES Modules、CommonJS
以下是三种模块化的不同写法:在index.js文件中引入a.js
-
ES Modules
export default function(a, b) { return a + b; } import a from './a.js'; -
CommonJS
module.exports = function(a, b) { return a + b; } var a = require('./a'); -
AMD(RequireJS)
define( function(require, factory) { 'use strict'; return function(a, b) { return a + b; } }); require(['./a'], function(a) { console.log(a(5, 5)); })
配置webpack:
-
安装nodeJS
-
npm init 初始化包,一直按回车配置文件,文件目录下会多出来一个package.json文件
-
node -v;npm -v检查node和npm的版本,确认安装成功;可以用where node查看node安装路径
-
安装webpack:npm i webpack@4.26.1 webpack-cli@3.1.2 -D;同样可以用webpack -v检查是否安装成功
-
在根目录下新建src文件夹,在该文件下设立index.js入口文件(index.js为默认的入口文件)
-
输入webpack命令,将index.js文件打包,文件目录下会多出来一个dist文件
-
但是控制台会出现一个警告,在webpack 4中需要设置mode模式。例:webpack --mode development。
-
但是每次都要设置太烦了,可以在package文件中进行配置
"scripts": { "build": "webpack --mode production" }, -
然后通过npm run build命令构建文件(效果一致)
-
--watch | -w 检测文件的改变,不需要没改变一次就重新运行一次。在package文件里配置即可。ctrl + c 取消监听
"scripts": { "build": "webpack --mode production --watch", "dev": "webpack --mode development" }, -
在引入模块的时候,可以再通过一些命令行,得到详细的打包信息,看到打包的信息
-
--progress 观察打包进度
-
--display-reasons 显示原因
-
--colors 以多样的颜色显示
"scripts": { "build": "webpack --mode production --watch --progress --display-reasons --colors", "dev": "webpack --mode development" }, -
-
single entry 入口文件:在src文件夹下面
-
出口文件:main
-
最后三行的白色文字部分,展示打包原因
-
最后三行的红色文字部分(index.js)引入青色文字部分的模块(a.js),以彩色的形式显示
dev配置
安装dev:npm install webpack-dev-server@3.1.10 -D
-
inline:内联/iframe模式,一般都不设定,设定为false的时候会有一个状态条
-
open:在服务器启动后打开浏览器
-
openPage:打开的页面,如果不是index.html,是找不到页面的,除非设置了这个属性
-
hot:启用webpack的热模块替换功能
-
port:自定义端口
-
historyApiFallback:使用HTML5历史记录API时,index.html会代替任何404回复,也可以设定跳转到什么页面上
-
输入http://localhost:3000/a,会跳转到a.html,相当于重定向
devServer: { open: true, port: 3000, historyApiFallback: { rewrites: [{ from: '/a', to: '/a.html' }] } }, -
proxy:拥有单独API后端开发服务器后,希望在同一域上发送API请求时,代理某些URL会很有用
-
target:目标接口
-
changeOrigin:如果不加这个就无法跳转请求
-
logLevel:日志
-
overlay:是否显示错误在页面中
Eslint语法检测
是ECMAScript/JavaScript代码中识别和报告模式匹配的工具,也就是检查代码规范的工具
配置相关插件:
npm i eslint@5.10.0 eslint-config-standard@12.0.0 eslint-loader@2.1.1 eslint-plugin-promise@4.0.1 eslint-plugin-node@8.0.0 eslint-plugin-html@5.0.0 eslint-plugin-standard eslint-plugin-import@2.14.0 -D
新建一个eslint配置文件:.eslintrc.js
module.exports = { // 在当前目录层级上筛选 root: true, // 筛选标准 extands: 'standard', // 在哪些文件中筛选js文件 plugins: ['html', 'promise', 'node'], // 设置环境 ebv: { browser: true, node: true }}
babel 转换编译
配置步骤:
-
npm init
-
npm i webpack webpack-cli -D
-
新建src文件夹,在该文件夹下设置入口文件
-
npm i babel-loader@7.1.5 babel-core -D
-
新建webpack.config.js文件,进行配置,是专门给webpack打包工具配置的文件
var path = require('path');module.exports = { entry: { app: './src/app.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: "[name].bundle.js" }, // 处理第三方文件 module: { rules: [{ // 用babel-loader处理以js为后缀的文件 test: /\.js$/, use: 'babel-loader', // 排除node_modules里的js文件,提高打包效率 exclude: /(node_modules)/ }] } } -
npm i babel-preset-env -D 不同的浏览器和平台对ES6,ES7,ES8的支持情况不一致, babel-preset-env可以按需加载插件,比起preset的其他版本更加灵活
-
新建.babelrc文件,配置babel
-
targets指定运行环境
-
targets.node 指定node版本
-
targets.browsers 指定浏览器版本
-
modules 指定何种形式的模块,设置为false表示不转码模块
{ "presets": [ ["env", { // 指定运行环境 "target" : { // 浏览器最新的两个版本运行 "browsers": ["lasty 2 versions"] } }] ]}
- npm i babel-polyfill -D 在有部分代码无法转码时使用垫片
- 在入口文件最顶部引入垫片
import 'babel-polyfill';
- webpack --mode none
全局 | 局部垫片
polyfill
babel默认只转换新的js语法,而不转换新的API(即方法和函数,比如generator、set、maps、symbol、promise等全局对象,以及一些定义在全局对象上的方法【Object.assign】,还有ES6新增的Array.from方法,babel也不会转码),所以需要使用babel-polyfill,为当前环境提供一个垫片,使各个浏览器保持相同的API:
npm i babel-polyfill -D- 在入口文件最顶部引入垫片:
import 'babel-polyfill'; - 优点:一次性解决所有兼容性问题,而且是全局的
transform-runtime
在webpack中,babel-plugin-transform-runtime实际上是依赖babel-runtime,因为在babel编译过程中,babel-plugin-transform-runtime这个插件会自动polyfill ES5不支持的特性。
- 这些polyfill包就在babel-runtime这个包里。
- babel-runtime和babel-transform-runtime的区别是,前者是手动挡,每当转译一个API都需要手动加上require(‘babel-runtime’);后者是自动挡,会由工具自动添加babel-transform-runtime
使用步骤:
-
如果之前下载了polyfill,先卸载 npm uninstall babel-polyfill
-
下载 npm i babel-runtime babel-plugin-transform-runtime -D 和 npm i babel-runtime -D。下载完之后package会自动添加babel-runtime 和 babel-plugin-transform-runtime的依赖
-
在.babelrc中配置插件
"plugins": [ "transform-runtime" ] -
webpack --mode none
优点:
- 无全局污染
- 依赖统一,按需引入,无重复引入,无多余引入(polyfill是各个模块共享)
- 适合用来编写lib(第三方库)类型的代码
处理CSS
style-loader
配合css-loader使用,将模块的导出作为样式添加到 DOM 中
分类:
- style-loader:以标签的形式插入到页面中
- style-loader/url:以link标签的形式在html中插入。这种方式不推荐,因为在js文件中引入多个css文件会生成多个link标签,而html每个link标签都会发送一个网络请求。
- 这种方式配合使用的就不是css-loader了 ,而是file-loader
- style-loader/useable:这种方式会有use()和unuse()两个方法,决定是否引入样式
options配置:
- singleton:将嵌入的多个css文件样式合并到一个样式里
- attrs:在样式标签上添加属性
- insertInto:将style标签插入到特定标签中
- insertAt:top | bottom,决定样式标签插入的位置
- transform
css-loader
解析CSS 文件后,使用 import 加载,并且返回 CSS 代码
options配置:
-
modules:是否模块化
modules: true -
模块化之后,会将类名变成哈希值,不会污染全局的类名
-
给元素设置类名就在入口文件中设置即可
-
但是className方法只能设定一个类名,如果要引入多个类名,就需要composes
.box1 { composes: box2 from './b.css'; width: 400px; height: 400px; background-color: red;}
document.getElementById('app').className = a.box1;
这样就两个类都引入了
编译顺序是先用css-loader将css代码编译,然后交给style-loader插入到html中去
file-loader
将文件(一般以图片文件为主,还包括字体文件等),在进行一些处理后,移动到输出文件夹
配置:webpack.config.js
var path = require('path');
module.exports = {
entry: {
app: './src/app.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js'
},
module: {
rules: [{
test: /\.css$/,
use: [{
loader: 'style-loader'
},{
loader: 'css-loader'
}],
exclude: /(node_modules)/
}]
}
}
在webpack中解析是从下到上解析的,所以先写style-loader,再写css-loader
在app.js文件顶部引入css文件,通过css-loader将文件引入,style-loader将文件动态插入到html中
import a from './css/a.css';
Postcss
将css解析成JavaScript可以操作的抽象语法树结构(Abstract Syntax Tree),可以使用插件去转换css
常用插件:
Autoprefixer:用于添加浏览器特定前缀,处理兼容性
postcss-cssnext:使用css将来版本中可能会加入的新特性(包含Autoprefixer)
cssnano:压缩优化css
Autoprefixer插件安装步骤:
-
将上一个项目复制过来,有了package.json的配置信息,可以直接npm install安装
-
下载postcss:
npm i postcss@7.0.6 postcss-cssnext@3.1.0 post-loader@3.0.0 cssnano@4.1.7 autoprefixer@9.3.1 -D -
新建postcss配置文件,postcss.config.js,配置插件
-
webpack.config.js中也添加配置信息
{ loader: 'postcss-loader'} -
运行之后可以看到兼容性已自动添加
postcss-cssnext和cssnano安装:
和上一个插件差不多,把postcss.config.js的配置修改一下即可
要注意的是,postcss-cssnext已经包含了autoprefixer了,之前autoprefixer的配置可以删除
可以看到设置的自定义属性,还是可以正常使用的
:root { --fontSize: 30px;}
.box { width: 400px; height: 400px; font-size: var(--fontSize); background-color: red; transition: width .2s linear; transform: rotate(10deg);}
Sass、Less
安装: npm i less less-loader sass sass-loader -D
同样在webpack配置文件中添加配置
loader: 'sass-loader'
使用less语法,能够被正常解析
@homecolor: pink;html { background-color: @homecolor;}
sass同理,要注意的是引入的包是sass-loader,sass文件后缀是scss
图片处理
url-loader
会将引入的图片编码,根据需求选择性把某些小图片编码成base64格式,写进页面,从而减少服务器请求,优化性能。
也就是说有两种工作情况:
- 文件大小<limit参数,将文件转为DataURL
- 文件大小>limit参数,url-loader会调用file-loader进行处理
是增强版的file-loader,url-loader包含了file-loader
使用步骤:
-
安装
-
配置webpack,在rules最顶部配置,防止出错
-
在入口文件中往html动态插入图片
var app = document.getElementById('app'); app.innerHTML = "<div class='item1'></div><div class='item2'></div><div class='item3'></div><div class='item4'></div>"; -
运行文件,file-loader会将图片放到dist文件夹中。
- 此处我们设置了文件路径,图片会挡在dist下面的imgs中,因为publicPath和outputPath结合起来就是dist/imgs
- 但是对于file-loader来说,limit是没有什么用的。换成url-loader就可以生效
url-loader和file-loader配置方法一致
image-webpack-loader压缩图片
npm i image-webpack-loader -D
配置:
插件
生成HTML - html-webPack-plugin@3.2.0
options:
- template:本地模板文件的位置,重写一份和模板一样的文件
- filename:输出文件的文件名称
- minify:压缩代码
- chunks: 允许插入到模板中的一些chunk,允许引入哪个入口文件所生成的js文件
- inject:向template或templateContent注入所有静态资源
**处理html文件中的图片 :**html-loader@0.5.5
自动处理文件路径
options:attrs:[img:src]
清除文件插件:clean-webpack-plugin@1.0.0
由于每次运行完都会生成新的js文件,使用这个插件可以清除dist文件夹,再重新生成文件,使用方法很简单,传入要清理的文件夹即可
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
app: './src/app.js',
main: './src/main.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: "[name].[hash:5].js"
},
module: {
rules: [{
test: /\.html$/,
use: {
loader: "html-loader",
options: {
// 对img标签的src进行处理
attrs: ["img: src"]
}
}
},{
test: /\.jpg$/,
use: {
loader: "file-loader",
options: {
name: "[name]-[hash:5].[ext]"
}
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: "./index.html",
filename: "app.html",
chunks: ['app'],
// 将js文件插入到body标签里面
inject: "body"
}),
new HtmlWebpackPlugin({
template: "./index.html",
filename: "main.html",
chunks: ['main']
}),
new CleanWebpackPlugin(['dist'])
]
}
插件配置完之后dist文件就会多出来index.html和图片文件
提取css样式
1. extract-text-webpack-plugin@next
fallback:当不提取的时候用什么方式加载到页面中
use:提取的方式处理css
使用这个插件之前,首先应该要在路口文件将css文件引入进来
import a from './css/a.css';import b from './css/b.less';
webpack配置如下:
var ExtractLess = require('extract-text-webpack-plugin');var CleanWebpackPlugin = require('clean-webpack-plugin');
{ test: /\.css$/, use: ExtractCss.extract({ // 将css文件以require的形式加载到入口文件中 fallback: { loader: 'style-loader' }, use: { loader: 'css-loader' } }) },{ test: /\.less$/, use: ExtractLess.extract({ // 将css文件以require的形式加载到入口文件中 fallback: { loader: 'style-loader' }, use: [{ loader: 'css-loader' },{ loader: 'less-loader' }] }) }
new ExtractCss({ filename: '[name]-[hash:5]-one.css' }), new ExtractLess({ filename: '[name]-[hash:5]-two.css' }),
**2. mini-css-extract-plugin@**0.4.5
使用方法:
var MinicssEctractPlugin = require('mini-css-extract-plugin');
{ test: /\.css$/, use: [{ loader: MinicssEctractPlugin.loader },{ loader: 'css-loader' }] },{ test: /\.less$/, use: [{ loader: MinicssEctractPlugin.loader },{ loader: 'css-loader' },{ loader: 'less-loader' }] }
new MinicssEctractPlugin({ filename: '[name]-[hash:5]-one.css' }),
使用成功后就会在dist文件夹下出现打包后的文件
引入库
1. bootstrap@3.3.7
使用npm i命令下载
在入口文件通过import引入css文件:
import 'bootstrap/dist/css/bootstrap.css';
我们可以在引入的库中看到文件目录:
字体文件需要相关的loader解析,也就是file-loader
var path = require('path');var HtmlWebpackPlugin = require('html-webpack-plugin');var CleanWebpackPlugin = require('clean-webpack-plugin');module.exports = { entry: { app: './src/app.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].bundle.js' }, module: { rules: [ { test: /\.css$/, use: { loader: 'style-loader' } },{ test: /\.css$/, use: { loader: 'css-loader' } },{ // 利用file-loader处理字体文件 test: /\.(eot|svg|ttf|woff|woff2)$/, use: [{ loader: 'file-loader', options: { name: 'app.[ext]' } }] } ] }, plugins: [ // 以index.html为模板,在dist中创建app.html new HtmlWebpackPlugin({ template: 'index.html', filename: 'app.html' }), new CleanWebpackPlugin(['dist']) ]
效果如下:
2. jQuery
通过npm i下载jQuery库
引入jQuery
import $ from 'jquery';
webpack.ProvidePlugin
上例中必须要通过import引入模块,webpack.ProvidePlugin不需要,它是webpack的内置模块,使用webpack.ProvidePlugin加载的模块在使用时不再需要import和require进行引入
var webpack = require('webpack');
new webpack.ProvidePlugin({ $: 'jquery' })
没有通过npm下载库,找不到路径没有关系,可以通过手动修改路径,引入本地文件
resolve: { alias: { jquery$: path.resolve(__dirname, 'libs/jquery.min.js') } }
imports-loader
允许使用依赖于特定全局变量的模块,对依赖全局变量$,或this作为window对象的第三方模块非常有用
但是这种方法还是要用import引入,resolve也要配置路径,还是第一种方法更简单点
test: path.resolve(__dirname, 'libs/jquery.min.js'), use: { loader: 'imports-loader', options: { $: 'jquery' } }
Tree Shaking
摇晃掉枯萎的叶子,也就是清除掉没有用到的文件
JS tree shaking
uglifyjs-webpack-plugin@2.1.1 可以更加精细的压缩代码
在minimizer中可以用,在plugins也可以用。
minimizer:true和webpack --mode production作用一样,也是可以压缩代码的。但是它的优先级更高,是在mode production压缩的基础上进行更精细的压缩配置,设定minimizer,要在mode production的前提下才能生效。
实际上mode production设置了之后,minimizer默认为true,如果minimizer为false,mode production无效。
module.exports = { optimization: { // minimize: true minimizer: [ new UglifyJS({ uglifyOptions: { ecma: 5 } }) ] }}
在插件中使用,要注意如果mode不是production,会全部压缩,只有mode production才会按需压缩,没有使用到的内容不会打包
var UglifyJS = require('uglifyjs-webpack-plugin');module.exports = { plugins: [ new UglifyJS({ uglifyOptions: { ecma: 5 } }) ]}
两种方法都可以
CSS true shaking
压缩:同样有两种方法
npm i optimize-css-assets-webpack-plugin@5.0.1 cssnano@4.1.8 -D
var UglifyJS = require('uglifyjs-webpack-plugin');var MiniCss = require('mini-css-extract-plugin');var OptimizeCss = require('optimize-css-assets-webpack-plugin');module.exports = { module: { rules: [ { test: /\.css$/, use: [{ // 插入 loader: 'style-loader' },{ // 压缩 loader: MiniCss.loader }, { // 打包 loader: 'css-loader' }] } ] }, optimization: { // minimize: true minimizer: [ new UglifyJS({ uglifyOptions: { ecma: 5 } }), new OptimizeCss({ cssProcessor: require('cssnano') }) ] }, plugins: [ new MiniCss({ filename: 'app.min.css' }), // new OptimizeCss({ // // 加载器 // cssProcessor: require('cssnano') // }) // new UglifyJS({ // uglifyOptions: { // ecma: 5 // } // }) ]}
去除无效样式
npm i purifycss-webpack@0.7.0 purify-css@1.2.5 glob@7.1.3 glob-all@3.1.0 -D
purifycss-webpack
purify-css 筛选没有用到的类名,对应的样式
glob-all,帮助purifyCSS进行路径处理,定位要做Tree Shaking的路径文件
var purifyCss = require('purifycss-webpack');var path = require('path');var glob = require('glob-all');
new purifyCss({ paths: glob.sync([ path.join(__dirname, './index.html'), path.join(__dirname, './src/index.js') ]) })
提取公共代码
提取了公共代码之后,虽然用户在第一次打开网站的速度得不到优化,但是当用户访问该网站的其他页面时,就可以直接在缓存中提取公共代码。这样做网页加载速度得到优化,网络传输流量得以减少,服务器成本也会降低。
webpack4.x会默认对代码进行拆分,规则如下:
- 模块被重复引用或者模块来自node_modules
- 在压缩前最小为30kb
- 在按需加载时,请求数量<=5
- 在初始加载时,请求数量<=3
但是一般情况下都是自定义查分规则,用下列工具细分代码
缓存组 Cache Groups
缓存组默认将node_modules中的模块拆分到一个叫做vendors的代码块中,将最少重复引用两次的模块放入default中
bundle-analyzer可视化工具,可以查看文件结构
npm i webpack-bundle-analyzer@3.0.3 -D
var path = require('path');var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;module.exports = { entry: { pageA: './src/pageA.js', pageB: './src/pageB.js' }, output: { path : path.resolve(__dirname, 'dist'), filename: '[name].bundle.js' }, plugins: [ new BundleAnalyzerPlugin() ], optimization: { // 分隔模块 splitChunks: { cacheGroups: { // 定义处理公共模块的内容,都是业务代码,没用其他库,都是自己写的 common: { // 拆分出来的块的信息 name: 'common', // 在所有模块中寻找 chunks: 'all', // 压缩前的最小模块大小 minSize: 1, // 优先级 priority: 0 }, vendor: { name: 'vendor', test: /[\\/]node_modules[\\/]/, chunks: 'all', // 先提取体积比较大的第三方库的代码,再提取业务代码 priority: 10 } } } }}
第三方库的代码另外提取到vendor中
代码分割
单页面的代码分割和懒加载不是通过webpack配置来实现的,而是通过webpack的写法和内置函数实现的
import()
进行动态加载,如果单独文件太大的话,加载可能会很慢,这个方法可以将打包后的js文件拆分成一个个小的js文件,然后通过script标签直接加载要页面里就可以了。
使用方法很简单,用import方法异步调用
import(/* webpackChunkName: 'subPageA'*/'./subPageA').then(function(subPageA) { console.log(subPageA);});
注释设定的是拆分的chunk的名称
后缀名再通过webpack配置文件配置一下,和打包的budle文件以示区分
output: { path: path.resolve(__dirname, 'dist'), filename: '[name].bundle.js', chunkFilename: '[name].chunk.js', }
第三方文件:
import(/* webpackChunkName: 'jquery'*/'jquery').then(function($) { console.log($);});
require.ensure()
webpack在编译时 ,会静态的解析代码中的require.ensure(),同时将模块添加到一个分开的chunk中。这个新的chunk会被webpack通过jsonp来按需加载
和import()一个个拆分不同,require.ensure()是将多个引用资源打包在一起
// 入口文件打包的结果会包括module模块require.include('./module');// subPageA和subPageB合在一起另外打包require.ensure(['./subPageA', './subPageB'], function() { var subPageA = require('./subPageA'); var subPageA = require('./subPageB');}, 'subPage');
第三方文件:
require.ensure(['jquery'], function(){ var $ = require('jquery'); console.log($);}, 'vendor')