基于
webpack3
# 一、webpack简介
# 1.1 版本更迭

大版本变化

# 1.2 功能进化
Webpack V1
- 编译、打包
HMR(模块热更新)- 代码分割
- 文件处理
Webpack V2
Tree ShakingES module- 动态
Import - 新的文档
Webpack V3
Scope Hoisting(作用域提升)Magic Comments(配合动态import使用)
版本迁移
V1 -> V2
迁移指南 https://doc.webpack-china.org/guides/migrating/
V2 -> V3
更新升级即可
# 二、webpack核心概念
# 2.1 Entry
- 代码的入口
- 打包的入口
- 单个或多个
写法建议使用键值对写法
module.exports = {
entry: 'index.js'
}
module.exports = {
entry: '[index.js','vendor.js']
}
module.exports = {
entry: {
index:'index.js'
}
}
module.exports = {
entry: {
index:['index.js','app.js'],
vendor: 'vendor.js'
}
}
# 2.2 Output
- 打包成的文件(
bundle) - 一个或多个
- 自定义规则
- 配合
CDN
module.exports = {
entry: 'index.js',
output: {
filename: 'index.min.js'
}
}
module.exports = {
entry: {
index: 'index.js',
vendor: 'vendor.js'
},
output: {
filename: '[name].min[hash:5].js'
}
}
# 2.3 Loaders
- 处理文件
- 转化为模块
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: 'css-loader'
}
]
}
}
# 2.3.1 常用Loader
编译相关
babel-loaderts-loader
样式相关
style-loadercss-loaderless-loaderpostcss-loader
文件相关
file-loaderurl-loader
# 2.4 Plugins
- 参与打包整个过程
- 打包优化和压缩
- 配置编译时的变量
- 极其灵活
module.exports = {
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
}
# 2.4.1 常用plugins
优化相关
CommonsChunkPluginUglifyJsWebpackPlugin
功能相关
ExtractTextWebpackPlugin提取cssHtmlWebpackPlugin生成HTML模板HotModuleReplacementPlugin热模块替换CopyWebpackPlugin拷贝文件
# 2.5 名词
Chunk打包过程分割的代码块Bundle打包后的文件Module
# 三、初探 webpack
# 3.1 使用babel打包es6
# 3.1.1 编译 ES 6/7
Babel
npm install babel-loader@8.0.0-beta.0 @babel/core
npm install –save-dev babel-loader babel-core
Babel Presets
主要有几种类型选择
es2015es2016es2017envbabel-preset-reactbabel-preset-stage 0 - 3
npm install @babel/preset-env –save-dev
npm install babel-preset-env –save-dev
Babel Polyfill
针对一些不能处理的函数方法(
Generator、Set、Map、Array.from...)需要用到babel-Polyfill处理
- 全局垫片
- 为应用准备
npm install babel-polyfill –save
import “babel-polyfill”
Babel Runtime Transform
- 局部垫片
- 为开发框架准备
npm install babel-plugin-transform-runtime –save-dev
npm install babel-runtime –save
例子
module.exports = {
entry: {
app: 'app.js'
},
output: {
filename: '[name].[hash:8].js'
},
module: {
rules:[
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',{
//指定target为根据哪些语法编译
targets: {
browsers: ['> 1%','last 2 versions']
}
}
]
}
},
exclude: '/node_modules'
]
}
}
对于
webpack中babel的配置可以单独提取处理.babelrc统一管理
{
"presets": [
["@babel/preset-env",{
targets: {
browsers: ['> 1%','last 2 versions']
}
}]
],
"plugins": [
"transform-runtime"
]
]
# 3.2 打包 Typescript
npm i typescipt ts-loader --save-dev
npm i typescipt awesome-typescript-loader --save-dev
配置
tsconfig.jsonwebpack.config.js
tsconfig
- 配置选项:官网
/docs/handbook/compiler-options.html - 常用选项
compilerOptionsincludeexclude
声明文件
用于编译时检查错误
以loadsh为例,需要安装@types/lodash带有声明文件的,而不是安装lodash
npm install @types/lodash
npm install @types/vue
Typings
也可以这样安装带有
type的包
npm install typings
typings install lodash
例子
module.exports = {
entry: {
'app': 'app.js'
},
output: {
filename: '[name].bundle.js'
},
module: {
rules: [
test: /\.tsx?$/,
use: {
loader: 'ts-loader'
}
]
}
}
在项目根目录创建
tsconfig.json
{
"compilerOptions": {
"module": "comonjs",
"target": "es5", //编译后的文件在哪个环境运行
"allowJs": true,//允许js语法
},
"include": [
//编译路径
"./src/*"
],
"exclude": [
//排除编译文件
"./node_modules"
]
}
# 3.3 提取 js 的公用代码
- 减少代码冗余
- 提高加载速度
主要使用内置插件实现
webpack.optimize.CommonsChunkPlugin
{
plugins: [
new webpack.optimize.CommonsChunkPlugin(option)
]
}
例子
module.exports = {
entry: {
"pageA": "./src/pageA",
"pageB": "./src/pageB",
"vendor": ['loash']//业务代码和第三方代码区分开,给loash单独打一个包
},
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].bundle.js',
chunkFilename: '[name].chunk.js'
},
plugins: [
// 提取common
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
minChunks:2,//出现两次就打包成common代码
chunks: ['pageA','pageB']//指定范围提取公共代码
})
// 提取vendor、取业务代码manifest
new webpack.optimize.CommonsChunkPlugin({
//把entry的vendor代码和这里的common(webpack打包的)代码合并
names: ['vendor','manifest']
minChunks: Infinity
})
// ==== 提取业务代码manifest== 合并到上面names中
// 如果不想把webpack打包的代码和vendor代码合并 需要提取到manifest
//new webpack.optimize.CommonsChunkPlugin({
// webpack代码和vendordiam区分开
// name: 'manifest' //manifest即生成
// minChunks: Infinity
// })
]
}

# 3.4 代码分割和懒加载
第一种方式:通过wepack内置方法
require.ensure动态加载一个模块,接收四个参数
[]:dependencies初次并不会执行callback的时候才会执行errorCallback可省略chunkName
第二种方式:通过ES2015 Loader Spec
System.import()后面演变为import()来动态加载模块
import()方式返回一个promise在import中传入需要依赖的明,动态加载模块,就可以像使用Promise一样使用import().then()
代码分割场景
- 分离业务代码 和 第三方依赖
- 分离业务代码 和 业务公共代码 和 第三方依赖
- 分离首次加载 和 访问后加载的代码
例子
目标是提取
pageA、pageB中公共的模块moduleA
运行打包这时loadash提取到vendor中

这时候还不是我们想要的

这时候这有
pageA中才有moduleA

新建一个html验证是否动态加载

import()动态加载的写法
合并了subPageA和subPageB



引入css
例子
例子
例子