Webpack 启动后会从Entry里配置的Module开始递归解析 Entry 依赖的所有 Module。 每找到一个 Module, 就会根据配置的Loader去找出对应的转换规则,对 Module 进行转换后,再解析出当前 Module 依赖的 Module。 这些模块会以 Entry 为单位进行分组,一个 Entry 和其所有依赖的 Module 被分到一个组也就是一个 Chunk。最后 Webpack 会把所有 Chunk 转换成文件输出。 在整个流程中 Webpack 会在恰当的时机执行 Plugin 里定义的逻辑。
1 | module.exports = { |
1.entry
指定webpack开始构建的入口模块,从该模块开始构建并计算出直接或间接依赖的模块或者库
- entry配置
- 只有一个入口文件时:是一个字符串,如:
entry:'./src/index.js'
- 有两个及以上入口文件时:是一个对象
- 是数组时,是将多个模块打包成一个模块。依赖性最高的放在最后
- 是键值对时,是需要分别打包多个模块,每一个文件都单独打包成一个文件
- 只有一个入口文件时:是一个字符串,如:
1 | // 1.写成数组的方式就可以打出多入口文件,不过这里打包后的文件都合成了一个 |
1 | module.exports = { |
2.output
告诉webpack如何命名输出的文件以及输出的目录
缓存
缓存无处不在,使用缓存的最好方法是保证你的文件名和文件内容是匹配的(内容改变,名称相应改变)
webpack可以把一个哈希值添加到打包的文件名中,使用方法如下,添加特殊的字符串混合体([name], [id] and [hash])到输出文件名前
1 | module.exports = { |
现在用户会有合理的缓存了。
3.loaders
Loaders
是webpack
提供的最激动人心的功能之一了。通过使用不同的loader
,webpack
有能力调用外部的脚本或工具,实现对不同格式的文件的处理,比如说分析转换scss为css,或者把下一代的JS文件(ES6,ES7)转换为现代浏览器兼容的JS文件,对React的开发而言,合适的Loaders可以把React的中用到的JSX文件转换为JS文件。
Loaders需要单独安装并且需要在webpack.config.js
中的module
下的rules
中进行配置,Loaders的配置包括以下几方面:
test
:一个用以匹配loaders所处理文件的拓展名的正则表达式(必须)use
: 一个数组,里面放需要执行的loader,倒序执行,从右至左。loader
:loader的名称(必须)options
: 为loaders提供额外的设置选项(可选)
include/exclude
:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
loader 名称 | 功能描述 |
---|---|
babel-loader | 将你的 (ES6,ES7…)的代码编译为浏览器支持的ES5的代码,jsx等 |
css-loader | 使你能够使用类似@import 和 url(...) 的方法实现 require() 的功能 |
style-loader | 将所有的计算后的样式加入页面html中的style标签 |
less-loader | 预处理器 |
postcss-loader | CSS的处理平台 |
file-loader | 将项目中定义加载的图片通过webpack编译打包,并返回一个编码后的公共的url路径 |
url-loader | 功能同file-loader,多一个可配置的limit值, 把图片进行base64编码 |
安装依赖包
1 | // babel编译 |
配置项:
1 | module.exports = { |
babel配置:
1 | //.babelrc |
CSS module
在过去的一些年里,JavaScript通过一些新的语言特性,更好的工具以及更好的实践方法(比如说模块化)发展得非常迅速。模块使得开发者把复杂的代码转化为小的,干净的,依赖声明明确的单元,配合优化工具,依赖管理和加载管理可以自动完成。
不过前端的另外一部分,CSS发展就相对慢一些,大多的样式表却依旧巨大且充满了全局类名,维护和修改都非常困难。
被称为CSS modules
的技术意在把JS的模块化思想带入CSS中来,通过CSS模块,所有的类名,动画名默认都只作用于当前模块。Webpack对CSS模块化提供了非常好的支持,只需要在CSS loader中进行简单配置即可,然后就可以直接把CSS的类名传递到组件的代码中,这样做有效避免了全局污染。
我们在app文件夹下创建一个Greeter.css
文件来进行一下测试
1 | /* Greeter.css */ |
导入.root
到Greeter.js中
1 | import React, {Component} from 'react'; |
放心使用把,相同的类名也不会造成不同组件之间的污染。
1 | <div class="Greeter__root--16xre"> |
4.plugins
插件(Plugins)是用来拓展Webpack功能的,它们会在整个构建过程中生效,执行相关的任务。
Loaders和Plugins常常被弄混,但是他们其实是完全不同的东西,可以这么来说,loaders是在打包构建过程中用来处理源文件的(JSX,Scss,Less..),一次处理一个,插件并不直接操作单个文件,它直接对整个构建过程其作用。
Webpack有很多内置插件,同时也有很多第三方插件,可以让我们完成更加丰富的功能。
plugin 名称 | 功能描述 |
---|---|
html-webpack-plugin | 根据index.html模版,生成一个自动引入打包后js文件的index.html |
extract-text-webpack-plugin | 静态资源处理器 , 分离CSS和JS文件, 不能喝style-loader同时使用 |
clean-webpack-plugin | 去除dist 文件中的残余文件 |
webpack.HotModuleReplacementPlugin | 热加载插件 |
webpack.OccurrenceOrderPlugin | 为组件分配ID,通过这个插件webpack可以分析和优先考虑使用最多的模块,并为它们分配最小的ID |
webpack.UglifyJsPlugin | 代码压缩和注释删除等压缩手段, 减小打包后项目的体积 |
happypack | 在node中打包的时候开启多个子进程去并发执行,子进程处理完后把结果交给主进程 |
webpack.optimize.ModuleConcatenationPlugin | 如果你的项目是用ES2015的模块语法,并且webpack3+,把所有的模块放到一个函数里,减少了函数声明,文件体积变小,函数作用域变少。 |
webpack.BannerPlugin | 添加版权声明 |
webpack.NamedModulesPlugin | 显示模块的相对路径 |
安装依赖包
1 | // 生成HTML |
配置项:
1 | const webpack = require('webpack'); |
5.resolve
1 | module.exports = { |
不同环境:线上和线下
在生产环境和开发环境其实我们的配置是存在相同点,和不同点的,为了处理这个问题,会创建3个文件:
webpack.base.js
: 共同的配置webpack.dev.js
: 在开发环境下的配置webpack.prod.js
: 在生产环境的配置
通过webpack-merge去做配置的合并,比如:
开发环境
1 | const path = require('path'); |
开发环境中我们可以启动一个devServer静态文件服务器,预览我们的项目,引入base配置文件,用merge去合并配置。
生产环境
再来看看生产环境最重要的代码压缩,混淆:
1 | const path = require('path'); |
webpack-parallel-uglify-plugin
可以并行压缩代码,提升打包效率
5.Chunk
coding split的产物,我们可以对一些代码打包成一个单独的chunk,比如某些公共模块,去重,更好的利用缓存;或者按需加载某些功能模块,优化加载时间。
在webpack3及以前我们都利用CommonsChunkPlugin
将一些公共代码分割成一个chunk,实现单独加载。
在webpack4 中CommonsChunkPlugin
被废弃,使用SplitChunksPlugin
6.devServer
npm install --save-dev webpack-dev-server
构建本地服务器,让你的浏览器监听你的代码的修改,并自动刷新显示修改后的结果 ,仅开发阶段
devserver的配置选项 | 功能描述 |
---|---|
contentBase | 默认webpack-dev-server会为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录(本例设置到“public”目录) |
port | 设置默认监听端口,如果省略,默认为”8080“ |
inline | 设置为true ,当源文件改变时会自动刷新页面 |
historyApiFallback | 在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true ,所有的跳转将指向index.html |
配置项:
1 | module.exports = { |
在package.json
中的scripts
对象中添加如下命令,用以开启本地服务器:
1 | "scripts": { |
7.产品阶段的构建
在package.json
中的scripts
对象中添加
1 | //package.json |
npm run dev 是我们开发环境下打包的文件,当然由于devServer帮我们把文件放到内存中了,所以并不会输出打包后的dist文件夹
npm run build 就是我们打包后的文件,这是生产环境下,上线需要的文件
1 | // 一个常见的`webpack`配置文件 |