Webpack是一个打包模块化JavaScript的工具,在Webpack里一切文件皆模块,经过Loader转换文件,经过Plugin注入钩子,最后输出由多个模块组合成的文件。Webpack专一于构建模块化项目,称为模块打包机。css
入口,Webpack执行构建的第一步将从entry开始,可抽象成输入;html
module.exports = {
entry: './main.js'
};
复制代码
输出结果,在Webpack通过一系列处理并获得最终想要的代码后输出结果;vue
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist');
}
};
复制代码
模块转换器,用于将模块的原内容按照需求转换成新内容;node
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist');
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader?minimize'],
}
]
}
};
复制代码
扩展插件,在Webpack构建流程中的特定时机注入扩展逻辑,来改变构建结果或咱们想作的事情;react
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist');
},
module: {
rules: [
{
test: /\.css$/,
loaders: ExtractTextPlugin.extract({
use: ['css-loader']
})
}
]
},
plugins: [
new ExtractTextPlugin({
fliename: `[name]_[contenthash:8].css`,
})
]
};
复制代码
模块,在Webpack里一切皆模块,一个模块对应一个文件。Webpack会从配置的entry开始递归找出全部依赖的模块;jquery
代码块,一个chunk由多个模块组合而成,用于代码合并与分割;webpack
总结: Webpack在启动后会从Entry里配置的Module开始,递归解析Entry依赖的全部Module。每找到一个Module,就会根据配置的Loader去找出对应的转换规则,对Module进行转换后,再解析出当前Module依赖的Module。这些模块会以Entry为单位进行分组,一个Entry及其全部依赖的Module被分到一个组也就是一个Chunk。最后Webpack会将全部Chunk转换成文件输出,在整个流程中,Webpack会在恰当的时机执行Plugin里定义的逻辑。git
Webpack在寻找相对路径的文件时会以context为根目录,context默认为当前所在的工做目录,注意context必须是一个绝对路径的字符串。github
module.exports = {
context: path.resolve(__dirname, 'app'),
};
复制代码
类型 | 例子 | 含义 |
---|---|---|
String | './main.js' | 入口模块的文件路径,能够是相对路径 |
Array | ['./main.js', './app.js'] | 入口模块的文件路径,能够是相对路径 |
Object | {a: './main.js', b: './app.js'} | 配置多个入口,每一个入口生成一个chunk |
chunk的名称和entry的配置有关,若是entry是一个String或Array,只会生成一个chunk;若是entry是一个Object,就会生成多个chunk,名称为Object中的key。web
若是不肯定有多少个页面入口,能够设置为一个函数动态的返回entry配置;
// 同步函数
entry: () => {
return {
a: './page1/index',
b: './page2/index'
}
}
// 异步函数
entry: () => {
return new Promise( (resolve) => {
resolve({
a: './page1/index',
b: './page2/index'
})
})
}
复制代码
filename是配置输出的文件名称,为string类型,若是只有一个输出文件能够写死为bundle.js,可是有多个输出时能够借助模板变量[name].js
,经常使用的变量包括:
变量名称 | 含义 |
---|---|
id | Chunk的惟一标识,默认从0开始 |
name | Chunk的名称 |
hash | Chunk的惟一标识的Hash值,[hash:8]表明取8位Hash值,默认是20位 |
chunkhash | Chunk内容的Hash值,取值同上 |
用于指定在运行过程当中生成的Chunk在输出时的文件名称,常见场景为使用CommonChunkPlugin;支持和filename一致的内置变量;
配置输出文件的本地目录,为string类型的绝对路径,支持字符串模板,内置变量只有一个Hash;
module.exports = {
output: {
path: path.resolve(__dirname, 'dist_[hash]')
}
};
复制代码
配置发布到线上资源的URL前缀,为string类型的相对路径,默认为'',也支持字符串模板,内置变量只有一个Hash;
module.exports = {
output: {
filename: '[name]_[chunkhash:8].js',
publicPath: 'https://XX.cdn.com/static/'
}
};
复制代码
Webpcak输出的部分代码块可能须要异步加载,是经过JSONP方式实现的,因此能够在<script>
标签中设置crossorigin属性,经常使用来获取异步加载的脚本执行时的详细错误信息。
crossorigin属性值 | 含义 |
---|---|
anonymous(默认) | 在加载此脚本资源时不会带上用户的cookie |
use-credentials | 在加载此脚本资源时会带上用户的cookie |
当用Webpack去构建一个能够被其余模块导入使用的库时,须要用到LibraryTarget和library,它们一般搭配在一块儿使用,推荐使用Rollup来构建基础库;
LibraryTarget配置以何种方式导出库,经常使用的有var/this/commonjs/window/global等;
Library配置导出库的名称,配合LibraryTarget一块儿使用;
复制代码
配置为要导出的模块中哪些子模块须要被导出,它只有在output.libraryTarget被设置为commonjs或者commonjs2时使用才有意义;
// 某模块源代码
export const a = 1;
export default b = 2;
// 若是在output.libraryExport设置为a;那么将构建输出的代码和使用方法将变成如下内容:
// Webpack输出的代码
module.export = lib_code['a'];
// 使用库的方法
require('library-name') === 1;
复制代码
rules配置模块的读取和解析规则,一般用来配置Loader。类型为数组,数组里的每一项都描述了如何处理部分文件,每一项大体有以下三种方式来完成;
module.exports = {
module: {
rules: [
{
test: /\.js$/,
use: [{
loader: 'babel-loader',
options: {
cacheDirectory: true
},
enforce: 'post'
}],
include: path.resolve(__dirname, 'src'),
},
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
exclude: path.resolve(__dirname, 'node_modules')
}
]
}
};
复制代码
该可选配置项可让Webpack忽略对部分没采用模块化的文件的递归解析和处理,从而提升构建性能,类型为RegExp、[RegExp]、Function中的一种,注意被忽略的文件里不能包含import、require、define等模块化语句,否则会致使在浏览器中没法执行该模块化语句;
// 正则形式
noParse: /jquery|chartjs/
// 函数形式
noParse: (content) => {
return /jquery|chartjs/.test(content);
}
复制代码
该配置项能够精确到语法层面,让Webpack只解析对应的模块化文件;
module.exports = {
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader'],
include: path.resolve(__dirname, 'src'),
parser: {
amd: false,
commonjs: true,
requirejs: false,
harmony: true
}
}
]
}
};
复制代码
该配置项经过别名来将原导入路径映射成一个新的导入路径;
module.exports = {
resolve: {
alias: {
@components: './src/common/components',
@assets: './src/common/assets'
}
}
};
复制代码
有一些第三方模块会针对不一样的环境提供几份代码,例如分别提供ES5和ES6两份代码,Webpack会根据mainFields的配置去决定优先采用哪份代码,若是想优先采用ES6的代码,则能够这样配置:
mainFields: ['jsnext:main', 'browser', 'main'],
复制代码
在导入语句没带文件后缀时,Webpack会自动带上后缀尝试访问文件是否存在,默认是:
extensions: ['.js', '.json'],
复制代码
若是咱们想让Webpack优先使用typescript文件,则能够这样配置:
extensions: ['.ts', '.js', '.json']
复制代码
配置Webpack去哪些目录下寻找第三方模块,有时候咱们项目中的大量模块会放在common下面,则能够这样去配置:
modules: ['./src/common', 'node_modules']
复制代码
该配置项是描述第三方模块的文件名称,也就是package.json文件,默认以下:
descriptionFiles: ['package.json']
复制代码
若是resolve.enforceExtension为true,则全部导入语句都必须带后缀,如import './main.js';
和resolve.enforceExtension做用相似,专门针对node_modules下的模块生效,由于第三方模块大部分是不带后缀的,若是resolve.enforceExtension设置为true了,须要把resolve.enforceModuleExtension设为false来兼容第三方模块;
Plugin的配置很简单,plugins接收一个数组,数组中的每一项都是一个Plugin的实例,Plugin的参数经过构造函数传入;
module.exports = {
plugins: [
new CommonChunkPlugin({
name: 'common',
chunks: ['a', 'b']
})
]
};
复制代码
开启模块热替换功能,在不刷新整个页面的状况下,经过用新模块替换老模块来作到实时预览;
用于配置是否将这个代理客户端自动注入将运行在页面中的chunk里,默认自动注入;
-- 若是开启inline,则devserver会在构建变化后的代码时经过代理客户端控制网页刷新;
-- 若是关闭inline,则devserver会经过iframe的方式去运行要开发的网页,在构建完变化后的代码时,会经过刷新iframe来实现实时预览,这时须要去http://localhost:8080/webpack-dev-server/ 实时预览本身的网页;
用于方便的开发使用了HTML5的History API的单页应用,老是返回同一个html文件,浏览器会从URL里解析出当前页面的状态,从而显示对应的界面;
用来配置devserver HTTP服务器的文件根目录,在默认状况下为当前的执行目录,一般是项目的根目录,因此在通常状况下没必要设置;
能够在http响应中注入一些http响应头,使用以下:
module.exports = {
devServer: {
headers: {
'x-cookie': 12345
}
}
};
复制代码
用于配置devServer服务监听的地址,若是想让局域网的其余设备访问本身的本地服务,则能够在启动devserver时带上参数--host 0.0.0.0;
用于配置devServer服务监听的端口,默认使用8080端口,若是80端口被其余程序占用则依次+1类推;
配置一个白名单列表,只有http请求的host在该列表中才会正常返回;
配置是否关闭用于DNS从新绑定的http请求的host检查,devserver默认只接受本地的请求,关闭后能够接收来自任意host的请求;
devsever默认使用http服务,在某些状况下须要使用https服务时,能够开启此配置,此时devsever会自动为咱们在本地生成一份https证书,这时须要重启服务,如HTTP2和Service Worker就必须运行在https上;
配置客户端的日志等级,会影响咱们在浏览器控制台里看到的内容,默认为info级别,即输出因此类型(none/error/warning/info)的日志;
配置是否启用Gzip压缩,为Boolean类型,默认为false;
用于在devserver启动且第一次构建完成时,自动用系统默认浏览器打开咱们开发的页面,还提供了openPage配置项来打开指定URL的页面;
target配置可让Webpack构建除针对不一样运行环境的代码,常见的有:
target值 | 含义 |
---|---|
web | 针对浏览器(默认),全部代码都集中在一个文件里 |
node | 针对nodejs,使用require语句加载chunk代码 |
async-node | 针对nodejs,异步加载chunk代码 |
webworker | 针对webworker |
electron-mian | 针对Electron主线程 |
electron-render | 针对Electron渲染线程 |
配置Webpack如何生成Source Map,默认值是false即不生成,若想构建出的代码生成Source Map方便调试,则能够这样配置:
module.exports = {
devtool: 'source-map'
};
复制代码
Webpack支持监听文件更新,在文件发生变化时从新编译,监听模式默认是关闭的,如想打开则配置为:
module.exports = {
watch: true
};
复制代码
在使用devserver时,监听模式默认开启;除此以外,还能够灵活的控制监听模式;
module.exports = {
watch: true,
watchOptions: {
// 不监听的文件或文件夹,支持正则匹配
ignored: /node_modules/,
// 监听到变化后会等300ms再去执行,防抖
// 默认是300ms
aggregateTimeout: 300,
// 判断文件是否发生变化经过不停地询问系统指定文件有没有变化
// 默认每秒询问1000次
poll: 1000
}
};
复制代码
用于告诉Webpack要构建的代码中使用了哪些不用被打包的模块,也就是说这些模版是外部环境提供的,Webpack在打包时能够忽略它们;
module.exports = {
externals: {
jquery: 'jQuery'
}
};
复制代码
用来告诉Webapck如何去寻找Loader,该配置项经常使用来加载本地的Loader,默认配置以下:
module.exports = {
resolveLoader: {
modules: ['node_modules'],
extensions: ['js', 'json'],
mainFields: ['loader', 'main']
}
};
复制代码
Loader名称 | 功能描述 |
---|---|
raw-loader |
加载文件原始内容(utf-8) |
val-loader |
将代码做为模块执行,并将 exports 转为 JS 代码 |
url-loader |
像 file loader 同样工做,但若是文件小于限制,能够返回 data URL |
file-loader |
将文件发送到输出文件夹,并返回(相对)URL |
Loader名称 | 功能描述 |
---|---|
json-loader |
加载 JSON文件(默认包含) |
json5-loader |
加载和转译 JSON 5文件 |
Loader名称 | 功能描述 |
---|---|
script-loader |
在全局上下文中执行一次 JavaScript 文件(如在 script 标签),不须要解析 |
babel-loader |
加载 ES2015+ 代码,而后使用 Babel 转译为 ES5 |
buble-loader |
使用 Bublé 加载 ES2015+ 代码,而且将代码转译为 ES5 |
traceur-loader |
加载 ES2015+ 代码,而后使用 Traceur转译为 ES5 |
ts-loader 或 awesome-typescript-loader |
像 JavaScript 同样加载 TypeScript2.0+ |
coffee-loader |
像 JavaScript 同样加载 CoffeeScript |
Loader名称 | 功能描述 |
---|---|
html-loader |
导出 HTML 为字符串,须要引用静态资源 |
pug-loader |
加载 Pug 模板并返回一个函数 |
jade-loader |
加载 Jade 模板并返回一个函数 |
markdown-loader |
将 Markdown 转译为 HTML |
react-markdown-loader |
使用 markdown-parse parser(解析器) 将 Markdown 编译为 React 组件 |
posthtml-loader |
使用 PostHTML 加载并转换 HTML 文件 |
handlebars-loader |
将 Handlebars 转移为 HTML |
markup-inline-loader |
将内联的 SVG/MathML 文件转换为 HTML。在应用于图标字体,或将 CSS 动画应用于 SVG 时很是有用。 |
Loader名称 | 功能描述 |
---|---|
style-loader |
将模块的导出做为样式添加到 DOM 中 |
css-loader |
解析 CSS 文件后,使用 import 加载,而且返回 CSS 代码 |
less-loader |
加载和转译 LESS 文件 |
sass-loader |
加载和转译 SASS/SCSS 文件 |
postcss-loader |
使用 PostCSS加载和转译 CSS/SSS 文件 |
stylus-loader |
加载和转译 Stylus 文件 |
Loader名称 | 功能描述 |
---|---|
mocha-loader |
使用 mocha 测试(浏览器/NodeJS) |
eslint-loader |
PreLoader,使用 ESLint 清理代码 |
jshint-loader |
PreLoader,使用 JSHint 清理代码 |
coverjs-loader |
PreLoader,使用 CoverJS 肯定测试覆盖率 |
Loader名称 | 功能描述 |
---|---|
vue-loader |
加载和转译 Vue 组件 |
polymer-loader |
使用选择预处理器(preprocessor)处理,而且 require() 相似一等模块(first-class)的 Web 组件 |
angular2-template-loader |
加载和转译 Angular 组件 |
Plugin名称 | 功能描述 |
---|---|
AggressiveSplittingPlugin |
将原来的 chunk 分红更小的 chunk |
BabelMinifyWebpackPlugin |
使用 babel-minify进行压缩 |
BannerPlugin |
在每一个生成的 chunk 顶部添加 banner |
CommonsChunkPlugin |
提取 chunks 之间共享的通用模块 |
CompressionWebpackPlugin |
预先准备的资源压缩版本,使用 Content-Encoding 提供访问服务 |
ContextReplacementPlugin |
重写 require 表达式的推断上下文 |
CopyWebpackPlugin |
将单个文件或整个目录复制到构建目录 |
DefinePlugin |
容许在编译时(compile time)配置的全局常量 |
DllPlugin |
为了极大减小构建时间,进行分离打包 |
EnvironmentPlugin |
DefinePlugin 中 process.env 键的简写方式。 |
ExtractTextWebpackPlugin |
从 bundle 中提取文本(CSS)到单独的文件 |
HotModuleReplacementPlugin |
启用模块热替换(Enable Hot Module Replacement - HMR) |
HtmlWebpackPlugin |
简单建立 HTML 文件,用于服务器访问 |
I18nWebpackPlugin |
为 bundle 增长国际化支持 |
IgnorePlugin |
从 bundle 中排除某些模块 |
LimitChunkCountPlugin |
设置 chunk 的最小/最大限制,以微调和控制 chunk |
LoaderOptionsPlugin |
用于从 webpack 1 迁移到 webpack 2 |
MinChunkSizePlugin |
确保 chunk 大小超过指定限制 |
NoEmitOnErrorsPlugin |
在输出阶段时,遇到编译错误跳过 |
NormalModuleReplacementPlugin |
替换与正则表达式匹配的资源 |
NpmInstallWebpackPlugin |
在开发时自动安装缺乏的依赖 |
ProvidePlugin |
没必要经过 import/require 使用模块 |
SourceMapDevToolPlugin |
对 source map 进行更细粒度的控制 |
EvalSourceMapDevToolPlugin |
对 eval source map 进行更细粒度的控制 |
UglifyjsWebpackPlugin |
能够控制项目中 UglifyJS 的版本 |
ZopfliWebpackPlugin |
经过 node-zopfli 将资源预先压缩的版本 |
更多第三方Loader和Plugin,查看 awesome-webpack 列表。
本文整理于【深刻浅出Webpack】,若有错误,敬请雅正😄
更多精彩内容欢迎关注个人公众号【天道酬勤Lewis】