安装
使用 npm 的形式来安装到全局:$ npm install webpack -g
个人还是推荐直接安装到项目目录下:$ npm init
$ npm install webpack --save-dev
配置
在项目根目录新建webpack.config.js
文件, 在文件中写入:
module.exports = {
//各种配置
}
下面来详细说明, 上面代码中的各种配置
context - 基本目录
基本目录(绝对路径)用于解决entry
选项, 默认值: process.cwd()
{
context: __dirname + "/app",
}
entry - 入口文件
如果您传递了一个字符串:字符串将被解析为一个模块,该模块在启动时加载。
如果你通过一个数组:所有的模块都在启动时加载。最后一个是导出的。
单入口:
{
entry: './src/app.js'
}
{
entry: ["./entry1", "./entry2"]
}
多入口:
{
entry: {
page1: "./page1",
page2: ["./entry1", "./entry2"]
}
}
output - 输出文件
虽然entry可以配置多个入口点,但是只能有一个输出配置, output配置项是一个对象,包括一下配置:
output.filename - 输出文件名
entry 配置为单入口时
{
output: {
filename: 'bundle.js'
}
}
entry配置为多入口时
- [name] 被替换为块的名称
- [hash] 被编译的哈希所取代
- [chunkhash] 是由数据块的哈希取代
{
output: {
filename: '[name].js'
}
}
这里也可以指定目录, 如: 'static/js/[name].[hash].js'
, 那么js文件将生成到static/js
目录下
output.path - 输入目录
该配置为绝对目录
{
output: {
filename: '[name].js',
path: __dirname + '/built'
}
}
output.publicPath - 前缀路径
如果你最后想将webpack生成的文件放到cdn, 那么必须配置此项
{
output: {
path: __dirname + '/built',
publicPath: "/assets/"
}
}
{
output: {
path: __dirname + '/built',
publicPath: "http://www.xxx.com/assets/"
}
}
output.chunkFilename
非输入块的文件输出的文件名
- [id] 被替换为块的id
- [name] 被替换为块的名称
- [hash] 被编译的哈希所取代
- [chunkhash] 由数据块的哈希取代
{
output: {
filename: '[name].js',
chunkFilename: '[name].[chunkhash].chunk.js',
path: __dirname + '/built'
}
}
这里也可以指定目录, 如: 'static/js/[name].[chunkhash].chunk.js'
, 那么js文件将生成到static/js
目录下
output.sourceMapFilename - sourceMap输出文件名
这个用处不大,可以忽略不配置
- [file] 被JavaScript文件的文件名替换
- [id] 被替换为块的身份证
- [hash] 被编译的哈希所取代
{
output: {
filename: '[name].js',
sourceMapFilename: '[file].sourceMap.js',
path: __dirname + '/built'
}
}
output.devtoolModuleFilenameTemplate
默认或者不配置即可
默认值 (devtool=[inline-]source-map): "webpack:///[resource-path]"
默认值 (devtool=eval): "webpack:///[resource-path]?[loaders]"
默认值 (devtool=eval-source-map): "webpack:///[resource-path]?[hash]"
output.devtoolFallbackModuleFilenameTemplate
默认或者不配置即可
默认值: "webpack:///[resourcePath]?[hash]"
output.devtoolLineToLine
默认或者不配置即可
默认值: 禁用
output.hotUpdateChunkFilename
默认或者不配置即可
默认值: "[id].[hash].hot-update.js"
output.hotUpdateMainFilename
默认或者不配置即可
默认值: "[hash].hot-update.json"
output.jsonpFunction
默认或者不配置即可
默认值: "webpackJsonp"
output.hotUpdateFunction
默认或者不配置即可
默认值: "webpackHotUpdate"
output.library
如果设置,将导出包作为库。 output.library
作为名字。
如果您正在编写一个库,并希望将其发布为单个文件, 那么可以设置该项
output.libraryTarget
导出库的格式
"var"
"this"
"commonjs"
"commonjs2"
"amd"
"umd"
module - 模块
module.loaders - 加载器
loaders
整体有一个数组,单个配置是一个对象, 包括以下配置:
test: 匹配规则
exclude: 排除目录
include: 包含目录
loader: 加载器(字符串)
loaders: 加载器(数组)
{
module: {
loaders: [
test: /\.jsx$/,
include: [
path.resolve(__dirname, "app/src"),
path.resolve(__dirname, "app/test")
],
exclude: /node_modules/,
loader: "babel-loader"
]
}
}
注: 加载器后面的-loader
可以省略写成loader: "babel"
一些常用文件及加载器名称
文件类型 | 加载器 |
---|---|
.js |
babel-loader |
.ts |
ts-loader |
.coffee |
coffee-loader coffee-redux-loader |
.jsx |
jsx-loader react-hot-loader!jsx-loader |
.json .json5 |
json-loader json5-loader |
.txt |
raw-loader |
.css |
style-loader!css-loader style-loader!css-loader!autoprefixer-loader |
.less |
style-loader!css-loader!less-loader |
.scss |
style-loader!css-loader!scss-loader |
.styl |
style-loader!css-loader!stylus-loader |
.png .jpg .jpeg .gif .svg |
file-loader url-loader |
.woff .ttf |
file-loader url-loader |
.wav .mp3 |
file-loader url-loader |
.mpeg .mp4 .webm .ogv |
file-loader |
.html |
html-loader |
.md .markdown |
html-loader!markdown-loader |
.pug .jade |
pug-loader |
.hbs .handlebars |
handlebars-loader |
module.preLoaders, module.postLoaders
该配置格式和loaders
一样, 可以用于编译前检测eslint
等
{
module: {
loaders: [
test: /\.js|\.jsx$/,
loader: 'eslint-loader'
]
}
}
resolve
resolve.alias - 设置别名
{
resolve: {
alias: {
js: path.join(__dirname, "src/scripts")
}
}
}
设置别名后, 你想require('src/scripts/app.js')
只需要写成require('js/app.js')
即可
resolve.root - 默认搜索路径
包含模块的目录(绝对路径)。也可以是一个目录数组。
此设置应用于将单个目录添加到搜索路径中。
{
resolve: {
root: [
path.resolve('./app/modules'),
path.resolve('./vendor/modules')
]
}
}
`
resolve.modulesDirectories
默认或者不配置即可
默认值: ["web_modules", "node_modules"]
resolve.fallback
webpack没有在resolve.root 或者resolve.modulesDirectories找到的模块的一个目录(或者目录绝对路径的数组
resolve.extensions
应用于解决模块的扩展数组, 配置后, 数组里的扩展名在require
时可以省略
默认值: ["", ".webpack.js", ".web.js", ".js"]
{
resolve: {
extensions: ['', '.js', '.jsx'],
}
}
resolve.packageMains
默认或者不配置即可
默认值: ["webpack", "browser", "web", "browserify", ["jam", "main"], "main"]
resolve.packageAlias
默认或者不配置即可
resolve.unsafeCache
默认或者不配置即可
默认值: []
resolveLoader
该配置和resolve类似, 只不过是作用于loaders
resolveLoader.moduleTemplates
默认或者不配置即可
默认值: ["-webpack-loader", "-web-loader", "-loader", ""]
{
resolveLoader: {
moduleTemplates: ['*-loader']
}
}
externals
指定依赖关系
{
externals: {
'jquery': 'jQuery'
}
}
当jQuery为cdn直接在html中引用时, 必须配置此项
target
"web" 在web中使用(默认)
"node" 在nodejs中使用
"webworker"
"async-node"
"node-webkit"
"electron"
如果webpack打包后的代码需要在nodejs中运行, 该项需要配置成node
bail
报告第一个错误为硬性错误, 值为true或者false
profile
定时在每个模块捕捉信息
cache
缓存生成模块和和chunks来提高混合增l量编译时的性能。
启用watch模式会默认启动它。
可以传入 false禁用它。
你可以传递一个对象启用它并且让webpack把传递的对象作为缓存。用这种办法,你可以在混合编译器的编译回调中共享缓存。注意:不要在多配置的回调中共享缓存。
watch
进入监控模式,重建变化的文件
debug
把loader的模式切到debug
devtool
选一个开发工具来加快调试
eval 每个模块都用eval执行
source-map 触发SourceMap,详情看output.sourceMapFilename
hidden-source-map 同上,但不会在包中添加引用注释。
inline-source-map SourceMap被作为dataurl加入到js文件中。
eval-source-map 每个模块都用eval执行,并且SourceMap被作为dataurl加入到eval中。
cheap-source-map 没有映射的sourcemap,loaders的sourcemap不会启用。
cheap-module-source-map 没有映射的sourcemap,sourcemap就简单的映射到每一行。
{
devtool: "#inline-source-map"
}
devServer
用来配置 webpack-dev-server 的一些行为
{
devServer: {
contentBase: "./build",
}
}
plugins - webpack自带插件
插件配置是webpack中的难点, 下面将列出一些常用的插件配置方法
NormalModuleReplacementPlugin
用newResource 替换用resourceRegExp 匹配到的资源。
如果newResource 用的相对路径,则路径 相对于以前的资源。
如果newResource 用的是函数,预期重写该函数提供的对象的“request”属性。
使用方法: new webpack.NormalModuleReplacementPlugin(resourceRegExp, newResource)
{
plugins: [
new webpack.NormalModuleReplacementPlugin(resourceRegExp, newResource)
]
}
ContextReplacementPlugin
如果资源(或者目录)匹配resourceRegExp ,这个插件替换默认资源,递归标记,或者替换掉由各自分析 newContentResource 、newContentRecursive 、newContentRegExp 得到的正则。
如果 newContentResource 是相对路径,则其路径相对于之前的资源。
如果用的是函数,预期重写该函数提供的对象的“request”属性。
{
plugins: [
new webpack.ContextReplacementPlugin(
resourceRegExp,
[newContentResource],
[newContentRecursive],
[newContentRegExp]
)
]
}
IgnorePlugin
不为所提供的正则表达式匹配到的模块生成模块。
requestRegExp 匹配请求的正则。
contextRegExp (可选项)匹配上下文(目录)的正则。
{
plugins: [
new webpack.IgnorePlugin(requestRegExp, [contextRegExp])
]
}
PrefetchPlugin
为一个正常模块的请求。这个请求会在打包之前发生。这样会提高效率。
context 一个目录的绝对路径
request 一个正常的模块的请求字符串
{
plugins: [
new webpack.PrefetchPlugin([context], request)
]
}
ResolverPlugin
应用一个插件(或者一个插件组)到一个或者多个resolvers (types指定的)
plugins 一个插件(或者一个插件组),它会被用到resolver(s)
types 一个resolver的类型或者一个resolver的类型数组。(默认["normal"],resolver types: normal, context, loader)
{
plugins: [
new webpack.ResolverPlugin([
new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
], ["normal", "loader"])
]
}
EnvironmentPlugin
这个插件将允许您通过process.env引用环境变量
{
plugins: [
new webpack.EnvironmentPlugin([
"NODE_ENV"
])
]
}
在代码中: var env = process.env.NODE_ENV
BannerPlugin
给每一个chunk顶部加一个banner
banner 一个字符串,它将被包装在一个注释里
options.raw 如果为true,banner不会被包在注释里
options.entryOnly 如果为true,banner只会被添加到入口chunk
{
plugins: [
new webpack.BannerPlugin('这里是打包文件头部注释!', {
raw: false,
entryOnly: false
})
]
}
DedupePlugin (推荐使用)
搜索同样或者相似的文件,在output中去重。它会加重入口文件的开销,但会有效地缩小文件的大小。
这不会改变在所有模块的语义。别指望来解决多模块实例。在去重后,它们不会成为一个实例。
注意:在watch模式下不要用它,只有在生产环境中再去用
{
plugins: [
new webpack.optimize.DedupePlugin()
]
}
LimitChunkCountPlugin
限制 chunck数量。chunck会被合并只到合适。
options.maxChunks 块的最大数量
ptions.chunkOverhead 以字节为单位的每个块的额外开销
options.entryChunkMultiplicator 入口文件的一个系数(默认10)
{
plugins: [
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 5,
chunkOverhead: 1024,
entryChunkMultiplicator: 10
})
]
}
MinChunkSizePlugin
合并低于这个最小尺寸的小块, 近似大小。
options.minChunkSize: 小于这个数字的块将被合并
{
plugins: [
new webpack.optimize.MinChunkSizePlugin({
minChunkSize: 5
})
]
}
OccurrenceOrderPlugin (推荐使用)
给module和 chunk分配id。经常使用的id更低(更短)。这让ids变得可预测的,也可以减小文件体积。建议使用。
{
plugins: [
new webpack.optimize.OccurrenceOrderPlugin()
]
}
UglifyJsPlugin (推荐使用)
最小化所有JavaScript输出块。 loader切换到轻便模式。你可以传递一个对象,包含UglifyJS选项。你可以传递一个包含UglifyJS选项的对象
{
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]
}
其他选项:
sourceMap : 插件使用SourceMaps 标出出错模块的位置。会减慢编译速度。(默认true)
test, include, exclude :正则或者正则数组。用来筛选处理过的文件。(默认:test: /.js($|\?)/i)
重整名称配置
关于重整的变量名的具体配置。默认情况 mangle选项是on.但是你可以传递一个列表自己配置插件
{
plugins: [
new webpack.optimize.UglifyJsPlugin({
mangle: {
except: ['$super', '$ ', 'exports', 'require']
}
})
]
}
用了这个配置,webpack不会损坏 "$super", "$", "exports" 或者 "require"这些关键词
CommonsChunkPlugin (推荐使用)
- options.name 或 options.names (string 或[string]): commons chunk的名称。
传入一个已经存在的块名,这个块儿会被选中。
如果传递一个字符串数组,这等于多次调用插件为每个块名称。
如果省略并且设置了options.async 或 options.children 所有chunk都会被选中。否则options.name会被作为一个块名。 - options.filename(string) : 公共块的文件名模板。
可以像output.filename一样包含同一占位符 。
如果省略,源文件名不会变(一般是output.filename或者output.chunkFilename)。 - options.minChunks(number|Infinity|function(module, count) -> boolean): chunk数量的最低值。
这些chunk在它被移到 公共块前需要包含一个模块。
这个值必须大于2小于chunk总数。 - options.chunks (string[]) : 通过chunk名选择源chunk。
这个块必须是公共块的子块。如果忽略,所有 入口块都会被选中。 - options.children(boolean): 如果为真,所有公共chunk的子块都会被选中。
- options.async(boolean|string): 如果为真,一个新的异步chunk将作为options.name的子块儿和options.chunks的兄弟块儿被创建。它与options.chunks并行加载。
- options.minSize (number): 在公共块创建前所有公共块的最小值
1. 入口文件的 Common chunk
生成一个额外的包含入口点共享的通用模块的chunk
{
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: "commons",
// filename: "commons.js",
// minChunks: 3,
chunks: ["pageA", "pageB"]
})
]
}
注意: 你必须在入口点之前加载这个chunk
2. 显式的依赖 chunk
把你的代码折分为依赖和应用
{
entry: {
vendor: ["jquery", "other-lib"],
app: "./entry"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: "vendor",
filename: "vendor.js",
minChunks: Infinity
})
]
}
注意: 结合长期的缓存,你需要用chunk-manifest-webpack-plugin
这个插件来阻止vendor chunk
的变化。你还应该使用records
来确保稳定的模块id
3. 把公共模块移动到父chunk
用了代码分割,子模块可以用到公共模块。你可以把公共模块移动到父模块中
{
plugins: [
new webpack.optimize.CommonsChunkPlugin({
children: true
})
]
}
4. 提取异步公共块儿
{
plugins: [
new webpack.optimize.CommonsChunkPlugin({
children: true,
async: true
})
]
}
AggressiveMergingPlugin
一个更具侵略性的块合并策略的插件,即使是相似的块也会被合并,如果总尺寸减小到足够。作为一个在这些块中不常见的选项模块,可以将块树移动到父模块
options.minsizereduce: 默认值为: 1.5, 这意味着尺寸需要减少50%的块才会被合并
options.moveToParents
options.entryChunkMultiplicator
{
plugins: [
new webpack.optimize.AggressiveMergingPlugin({
chiminsizereduceldren: 1.5
})
]
}
HotModuleReplacementPlugin (推荐使用)
启用热模块替换
{
plugins: [
new webpack.HotModuleReplacementPlugin()
]
}
NoErrorsPlugin
{
plugins: [
new webpack.NoErrorsPlugin()
]
}
DefinePlugin
{
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"development"',
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify("5fa3b9"),
BROWSER_SUPPORTS_HTML5: true,
TWO: "1+1",
"typeof window": JSON.stringify("object")
})
]
}
DllPlugin 和 DllReferencePlugin
另讲
plugins - 第三方插件
FaviconsWebpackPlugin
https://github.com/jantimon/favicons-webpack-plugin
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
{
plugins: [
new FaviconsWebpackPlugin('my-logo.png')
]
}
WebpackBrowserPlugin
https://github.com/1337programming/webpack-browser-plugin
const WebpackBrowserPlugin = require('webpack-browser-plugin');
{
plugins: [
new WebpackBrowserPlugin();
]
}
WebpackShellPlugin
https://github.com/1337programming/webpack-shell-plugin
const WebpackShellPlugin = require('webpack-shell-plugin');
{
plugins: [
new WebpackShellPlugin({
onBuildStart: ['echo "Starting"'],
onBuildEnd: ['node openBrowser.js']
})
]
}
BellOnBundlerErrorPlugin
https://github.com/senotrusov/bell-on-bundler-error-plugin
const BellOnBundlerErrorPlugin = require('bell-on-bundler-error-plugin')
{
plugins: [
new BellOnBundlerErrorPlugin()
]
}
HtmlWebpackPlugin (推荐使用)
将打包好的的模块注入html文件
https://github.com/ampedandwired/html-webpack-plugin
const BellOnBundlerErrorPlugin = require('bell-on-bundler-error-plugin')
{
plugins: [
new HtmlWebpackPlugin({
inject: true,
chunks: ['commons', 'app'],
filename: 'index.html',
template: 'index.html',
favicon: faviconPath,
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true
}
})
]
}
RewirePlugin
https://github.com/jhnns/rewire-webpack
var RewirePlugin = require("rewire-webpack")
{
plugins: [
new RewirePlugin()
]
}
ExtractTextPlugin (推荐使用)
合并CSS文件
https://github.com/webpack/extract-text-webpack-plugin
var ExtractTextPlugin = require('extract-text-webpack-plugin')
{
module: {
loaders: [{
test: /\.css$/,
loader: ExtractTextPlugin.extract(['css?-autoprefixer', 'postcss'])
}]
},
plugins: [
new ExtractTextPlugin('[name].[contenthash].css')
]
}