模块化只在开发阶段,webpack负责
- 编译(ES6->ES5,兼容),
- 打包(把一个个分散的模块打包到一个bundle.js文件,避免频繁请求模块)
- 同时支持不同类型的文件,png、css...
webpack打包的结果
生成一个立即执行函数
(function(modules){
//....
_require_函数,加载模块,执行
})([fn1, fn2,...])
传入的参数是一个数组,其中的数组元素是一个个的函数,每个模块都会包裹在一个函数中,实现私有作用域
loader
webpack只能处理JS文件,loader帮忙加载处理其他类型的文件
- css-loader 负责打包,把css模块转成js,
- style-loader 使用css样式
- url-loader 不单独生成文件,直接生成一个Data URLs嵌入代码,url就可以表示内容 -- 适用体积较小的文件,
分类:
- 编译转换 - css-loader
- 文件操作 - file-loader 单独生成文件,bundle.js导出文件访问路径
- 代码检查 - eslint-loader
webpack模块加载方式
- ESModules import声明
- CommonJS require函数
- css样式代码中,@import,url函数
- HTML代码中,< img src={}/>
实现一个loader
loader负责资源文件从输入到输出的转换,最后输出结果必须是JavaScript 对于同一个资源,可以依次使用多个loader 插件 html-webpack-plugin 清理dist
自动刷新问题 - HMR hotmoduleReplacement
- 自动刷新 - 页面之前的操作会丢失
- 模块热替换 - 运行过程中实时替换模块,应用运行状态不受影响
devServer:{
hot: true
}
new webpack.HotModuleReplacementPlugin()
- 样式文件热更新开箱即用? -- 经过loader处理,样式可以自动处理,直接替换就可以
- JS文件没有规律,导出的可能是对象,函数,使用不确定
- 框架下的开发,每个文件有规律,脚手架创建的项目内部都继承了HMR方案
Tree Shaking -
不是某个具体选项,功能搭配使用结果 生产模式下自动使用
optimization:{
usedExport: true, //只导出被引用的
minimize: true //代码压缩
}
scope hosting 合并模块
将所有模块合并输出到一个函数中
optimization:{
concatenateModules: true
}
(webpack打包生成一个立即执行函数,参数数组元素,为每个模块对应的函数)
sideEffects
副作用:模块执行时,除了导出成员之外所做的事情
optimization:{
sideEffects: true //开启功能
}
------------package.json中
“sideEffects”:false //标识代码没有副作用
"sideEffects":[文件路径1,...]
Code Spliting 代码分割
并不是每个模块在启动时必要,分包-按需加载
- 多入口打包,适用传统多页应用程序
entry: {
index:'./scr/index.js',
other:'./src/other.js'
}
output: {
filename: '[name].bundle.js'
}
plugins:[
new HtmlWebpackPlugin({
title:'',
chunks:''
})
]
- 动态导入
webpack-dev-server
1.5
资源模块 - 加载其他类型模块
asset/resource 发送单独文件,并导出url asset/inline 带出资源url asset/source 导出资源源代码 asset 在导出data url和发送一个单独文件自动选择
module:{
rules:[
{
test:/\.png$/,
type:asset/...
}
]
}
1.6 loader
引入,处理其他类型文件,供应用程序使用
-
加载css, style-loader,css-loader
-
抽离,压缩css,
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
1.7 babel-loader
webpack自带加载js模块的功能,但只能做模块化打包,不能转化js代码
{
test: /\.js$/,
exclude: /node_modules/, //排除这个下面的文件
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
1.8 代码分离
把代码分离到不同的bundle中,减小入口文件大小
-
entry入口起点 多个入口文件,如果用了相同的模块,会被重复打包到各自bundle文件中
// entry: './src/index.js', entry: { index: './src/index.js', another: './src/another-module.js' }, //配置多入口 -- 相应的output内容也需修改 output: { filename: '[name].bundle.js', path: path.resolve(__dirname, './dist'), clean: true, //清理dist assetModuleFilename: 'images/[contenthash][ext]' }, -
防止重复
entry: { index: { import: './src/index.js', dependOn: 'shared' }, another: { import: './src/another-module.js', dependOn: 'shared' }, shared: 'lodash' } -
动态导入
- 懒加载/按需加载 使用时加载
- 预获取/预加载 网络空闲时加载
1.9 缓存
- 缓存本地代码
- 缓存第三方库
1.10
命令脚本优化,npm run start/build即可
"scripts": {
"start": "npx webpack serve -c ./config/webpack.config.dev.js",
"build": "webpack serve -c ./config/webpack.config.prod.js"
}
拆分配置文件 => config.dev prod.dev 提取公共配置,并合并
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.config.common');
const productionConfig = require('./webpack.config.prod');
const devConfig = require('./webpack.config.dev');
module.exports = (env) => {
switch (true) {
case env.development:
return merge(commonConfig, devConfig)
case env.production:
return merge(commonConfig, productionConfig)
default:
return new Error('no match config')
}
}