1、webpack 是什么
根据文档的定义:本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
2、webpack 四个核心概念
- 入口(entry) 入口,webpack 执行构建的第一步将从 Entry 开始,可抽象成输入
- 输出(output) 输出结果,在 Webpack 经过一系列处理并得出最终想要的代码后输出结果
- 加载器(loader) 模块转换器,用于把模块原内容按照需求转换成新内容。
- 插件(plugins) 扩展插件,在 Webpack 构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件的发生,在特定时机做对应的事情。
2.1entry
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 第一种用法 module.exports = { entry:'index.js' } 第二种用法 module.exports = { entry:['index.js','b.js'] } 第三种用法 module.exports = { entry:{ index:'index.js', b:'b.js' } }
|
推荐使用使用第三种方法,方便分清各个入口的定义
2.2output
1 2 3 4 5 6 7 8 9 10
| module.exports = { entry:{ index:'index.js', b:'b.js' }, output:{ path:path.resolve(__dirname,'dist'), filename:'[name].min.[hash:5].js' } }
|
在上面的例子中,
- output 中的 name 和 entry 中的 key 相对应
- output 的 filename 可以指定 hash。有两个值可以选择:
- [hash]:hash 值是特定于整个构建过程的。
- [chunkhash]:hash 值是特定于每一个文件的内容的。
我们理想的缓存设计是,在一次版本更新(重新构建)后,只有当一个文件的内容确实发生了变化,它才需要被重新下载,否则应使用缓存。
因此,以上两个值中更推荐的是[chunkhash]。你也可以阅读这篇官方的缓存指南了解更多细节。
2.3loader
- 作用: 通过使用不同的 Loader,Webpack 可以要把不同的文件都转成 JS 文件,比如 CSS、ES6/7、JSX 等
- 参数
- test:匹配处理文件的扩展名的正则表达式
- use:loader 名称,就是你要使用模块的名称
- include/exclude:手动指定必须处理的文件夹或屏蔽不需要处理的文件夹
- query:为 loaders 提供额外的设置选项
下面以 css-loader 为例
1 2 3 4 5 6 7 8 9 10 11
| module: { + rules:[ + { + test:/\.css$/, + use:['style-loader','css-loader'], + include:path.join(__dirname,'./src'), + exclude:/node_modules/ + } + ] },
|
- 常用的 loader
- 编译相关 babel-loader ts-loader
- 样式相关 style-loader css-loader less-loader postcss-loader
- 文件相关 file-loader url-loader
2.4plugins
- 参与打包的整个过程
- 打包优化和压缩
- 配置编译时的变量
- 用法(以压缩 js 插件为例)
1 2 3 4 5
| module.exports = { plugins: [ new UglifyjsWebpackPlugin() ] }
|
- 常用的 plugin
- 优化相关
- CommonsChunkPlugin
- UglifyjsWebpackPlugin
- 功能相关
- ExtractTextWebpackPlugin
- HtmlWebpackPlugin
- HotModuleReplacementPlugin
- CopyWebpackPlugin
3、webpack 的常用配置
3.1 配置开发服务器
1
| npm i webpack-dev-server -D
|
1 2 3 4 5 6 7
| + devServer:{ + contentBase:path.resolve(__dirname,'dist'), + host:'localhost', + compress:true, + port:8080 + }
|
- contentBase 配置开发服务运行时的文件根目录
- host:开发服务器监听的主机地址
- compress 开发服务器是否启动 gzip 等压缩
- port:开发服务器监听的端口
3.2 自动产出 html
1
| npm i html-webpack-plugin -D
|
1 2 3 4 5 6 7 8 9
| plugins: [ + new HtmlWebpackPlugin({ + minify: { + removeAttributeQuotes:true + }, + hash: true, + template: './src/index.html', + filename:'index.html' })]
|
- minify 是对 html 文件进行压缩,removeAttrubuteQuotes 是去掉属性的双引号
- hash 引入产出资源的时候加上哈希避免缓存
- template 模版路径
3.3 分离 css
因为 CSS 的下载和 JS 可以并行,当一个 html 文件很大的时候,我们可以把 css 单独提取出来
1
| npm install --save-dev extract-text-webpack-plugin
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| module: { + rules:[ + { + test:/\.css$/, + use: ExtractTextWebpackPlugin.extract({ + use:'css-loader' + }), include:path.join(__dirname,'./src'), exclude:/node_modules/ + } + ] }, plugins: [ + new ExtractTextWebpackPlugin('css/index.css')]
|
3.4 编译 less 和 sass
1 2
| npm i less less-loader -D npm i node-saas sass-loader -D
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const cssExtract=new ExtractTextWebpackPlugin('css.css'); const lessExtract=new ExtractTextWebpackPlugin('less.css'); const sassExtract=new ExtractTextWebpackPlugin('sass.css');
{ test:/\.less$/, use: lessExtract.extract({ use:['css-loader','less-loader'] }), include:path.join(__dirname,'./src'), exclude:/node_modules/ }, { test:/\.scss$/, use: sassExtract.extract({ use:['css-loader','sass-loader'] }), include:path.join(__dirname,'./src'), exclude:/node_modules/ },
|
3.5 处理 CSS3 属性前缀
为了浏览器的兼容性,有时候我们必须加入-webkit,-ms,-o,-moz 这些前缀
- Trident 内核:主要代表为 IE 浏览器, 前缀为-ms
- Gecko 内核:主要代表为 Firefox, 前缀为-moz
- Presto 内核:主要代表为 Opera, 前缀为-o
- Webkit 内核:产要代表为 Chrome 和 Safari, 前缀为-webkit
1
| npm i postcss-loader autoprefixer -D
|
1 2 3 4 5 6 7 8 9 10 11 12
| module.exports={ plugins:[require('autoprefixer')] } { test:/\.css$/, use: cssExtract.extract({ + use:['css-loader','postcss-loader'] }), include:path.join(__dirname,'./src'), exclude:/node_modules/ },
|
postcss-loader其它用法可以参考文档
3.6 转义 ES6/ES7
Babel 其实是一个编译 JavaScript 的平台,可以把 ES6/ES7,React 的 JSX 转义为 ES5
1
| npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 babel-preset-react -D
|
1 2 3 4 5 6 7 8 9 10 11
| { test:/\.jsx?$/, use: { loader: 'babel-loader', options: { presets: ["env","stage-0","react"] } }, include:path.join(__dirname,'./src'), exclude:/node_modules/ },
|
3.7 调试打包后的代码
webapck 通过配置可以自动给我们 sourcemaps 文件,map 文件是一种对应编译文件和源文件的方法
- source-map 把映射文件生成到单独的文件,最完整最慢
- cheap-module-source-map 在一个单独的文件中产生一个不带列映射的 Map
- eval-source-map 使用 eval 打包源文件模块,在同一个文件中生成完整 sourcemap
- cheap-module-eval-source-map sourcemap 和打包后的 JS 同行显示,没有映射列
1 2 3
| module.exports = { devtool:'eval-source-map' }
|
3.8watch
当代码发生修改后可以自动重新编译
1 2 3 4 5 6 7 8
| new webpack.BannerPlugin(''),
watch: true, watchOptions: { ignored: /node_modules/, //忽略不用监听变更的目录 aggregateTimeout: 500, //防止重复保存频繁重新编译,500毫秒内重复保存不打包 poll:1000 //每秒询问的文件变更的次数 },
|
3.9 拷贝静态文件
有时项目中没有引用的文件也需要打包到目标目录
1
| npm i copy-webpack-plugin -D
|
1 2 3 4
| new CopyWebpackPlugin([{ from: path.join(__dirname,'public'),//静态资源目录源地址 to:'./public' //目标地址,相对于output的path目录 }]),
|
3.10 打包先清空
1
| npm i clean-webpack-plugin -D
|
1
| new cleanWebpackPlugin(path.join(__dirname,'dist'))
|
3.11 压缩 js /css
1 2
| npm i -D purifycss-webpack purify-css npm i bootstrap -S
|
1 2 3 4 5 6 7 8 9
| { test:/\.css$/, use: cssExtract.extract({ use: [{ loader: 'css-loader', options:{minimize:true} },'postcss-loader'] }), }
|
1 2 3 4
| + new PurifyCSSPlugin({ + //purifycss根据这个路径配置遍历你的HTML文件,查找你使用的CSS + paths:glob.sync(path.join(__dirname,'src/*.html')) + }),
|
4、总结
1
| 以上是webpack核心概念总结,对概念的理解,有助于总体了解下webpack不同的作用,遇到相关问题,找对应的模块。
|