概念 webpack是一個現代javascript應用程式的模塊打包器。 當webpack處理你的應用程式時,它會遞歸構建一個依賴圖(包含了你的應用程式所需要每個模塊),然後把這些模塊打包到少數幾個budle文件中(通常是只有一個,會被瀏覽器載入,根據項目情況而定)。 這是令人難以置信的配置,但開始 ...
概念
webpack是一個現代javascript應用程式的模塊打包器。
當webpack處理你的應用程式時,它會遞歸構建一個依賴圖(包含了你的應用程式所需要每個模塊),然後把這些模塊打包到少數幾個budle文件中(通常是只有一個,會被瀏覽器載入,根據項目情況而定)。
這是令人難以置信的配置,但開始前,你只需要明白四個核心概念:entry、output、loaders、和plugins。
配置對象選項
webpack.config.js
const path = require('path');
module.exports = {
// click on the name of the option to get to the detailed documentation
// click on the items with arrows to show more examples / advanced options
entry: "./app/entry", // string | object | array
// Here the application starts executing
// and webpack starts bundling
output: {
// options related to how webpack emits results
path: path.resolve(__dirname, "dist"), // string
// the target directory for all output files
// must be an absolute path (use the Node.js path module)
filename: "bundle.js", // string
// the filename template for entry chunks
publicPath: "/assets/", // string
// the url to the output directory resolved relative to the HTML page
library: "MyLibrary", // string,
// the name of the exported library
libraryTarget: "umd", // universal module definition
// the type of the exported library
/* Advanced output configuration (click to show) */
},
module: {
// configuration regarding modules
rules: [
// rules for modules (configure loaders, parser options, etc.)
{
test: /\.jsx?$/,
include: [
path.resolve(__dirname, "app")
],
exclude: [
path.resolve(__dirname, "app/demo-files")
],
// these are matching conditions, each accepting a regular expression or string
// test and include have the same behavior, both must be matched
// exclude must not be matched (takes preferrence over test and include)
// Best practices:
// - Use RegExp only in test and for filename matching
// - Use arrays of absolute paths in include and exclude
// - Try to avoid exclude and prefer include
issuer: { test, include, exclude },
// conditions for the issuer (the origin of the import)
enforce: "pre",
enforce: "post",
// flags to apply these rules, even if they are overridden (advanced option)
loader: "babel-loader",
// the loader which should be applied, it'll be resolved relative to the context
// -loader suffix is no longer optional in webpack2 for clarity reasons
// see webpack 1 upgrade guide
options: {
presets: ["es2015"]
},
// options for the loader
},
{
test: "\.html$",
use: [
// apply multiple loaders and options
"htmllint-loader",
{
loader: "html-loader",
options: {
/* ... */
}
}
]
},
{ oneOf: [ /* rules */ ] },
// only use one of these nested rules
{ rules: [ /* rules */ ] },
// use all of these nested rules (combine with conditions to be useful)
{ resource: { and: [ /* conditions */ ] } },
// matches only if all conditions are matched
{ resource: { or: [ /* conditions */ ] } },
{ resource: [ /* conditions */ ] },
// matches if any condition is matched (default for arrays)
{ resource: { not: /* condition */ } }
// matches if the condition is not matched
],
/* Advanced module configuration (click to show) */
},
resolve: {
// options for resolving module requests
// (does not apply to resolving to loaders)
modules: [
"node_modules",
path.resolve(__dirname, "app")
],
// directories where to look for modules
extensions: [".js", ".json", ".jsx", ".css"],
// extensions that are used
alias: {
// a list of module name aliases
"module": "new-module",
// alias "module" -> "new-module" and "module/path/file" -> "new-module/path/file"
"only-module$": "new-module",
// alias "only-module" -> "new-module", but not "module/path/file" -> "new-module/path/file"
"module": path.resolve(__dirname, "app/third/module.js"),
// alias "module" -> "./app/third/module.js" and "module/file" results in error
// modules aliases are imported relative to the current context
},
/* alternative alias syntax (click to show) */
/* Advanced resolve configuration (click to show) */
},
performance: {
hints: "warning", // enum
maxAssetSize: 200000, // int (in bytes),
maxEntrypointSize: 400000, // int (in bytes)
assetFilter: function(assetFilename) {
// Function predicate that provides asset filenames
return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
}
},
devtool: "source-map", // enum
// enhance debugging by adding meta info for the browser devtools
// source-map most detailed at the expense of build speed.
context: __dirname, // string (absolute path!)
// the home directory for webpack
// the entry and module.rules.loader option
// is resolved relative to this directory
target: "web", // enum
// the environment in which the bundle should run
// changes chunk loading behavior and available modules
externals: ["react", /^@angular\//],
// Don't follow/bundle these modules, but request them at runtime from the environment
stats: "errors-only",
// lets you precisely control what bundle information gets displayed
devServer: {
proxy: { // proxy URLs to backend development server
'/api': 'http://localhost:3000'
},
contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location
compress: true, // enable gzip compression
historyApiFallback: true, // true for index.html upon 404, object for multiple paths
hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin
https: false, // true for self-signed, object for cert authority
noInfo: true, // only errors & warns on hot reload
// ...
},
plugins: [
// ...
],
// list of additional plugins
/* Advanced configuration (click to show) */
}
本文檔的目的是給這些概念提供一個高層次的大綱,同時提供鏈接給詳細概念的指定用例。
Entry
webpack會創建一個你所有應用程式的依賴圖。這個依賴圖的起始點就是已知的entry(入口)點。這個入口點告訴webpack從哪開始,並且根據已知依賴圖進行打包。你可以把應用程式的入口點當作上下文根或啟動你的應用程式的第一個文件。
在webpack配置對象的entry屬性中定義入口點。簡單示例如下:
module.exports = {
entry: './path/to/my/entry/file.js'
};
有幾種方式聲明entry屬性:
1、單個entry語法
const config = {
entry: './path/to/my/entry/file.js'
};
module.exports = config;
2、對象語法
const config = {
entry: {
app: './src/app.js',
vendors: './src/vendors.js'
}
};
3、多頁面應用
const config = {
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js'
}
};
Output
一旦你打包所有代碼,你仍需要告訴webpack打包到哪裡去。output屬性會告訴webpack如何對待你的代碼。
const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
};
以上這個例子,我們使用output.filename
和output.path
屬性告訴webpack打包的文件名和路徑
Loaders
這個配置項的目的是讓webpack關註你項目的所有代碼而非瀏覽器(這並不意味著它們會被打包到一起)。webpack把每一個文件(.css, .html, .scss, .jpg, etc.)作為一個模塊。然而,webpack只知道javascript。
webpack中的Loaders會轉換這些文件到模塊中,並添加到你的依賴圖中。
在一個較高的水平,在你的webpack配置中有兩個目的:
1、標識什麼文件應該用一個確定的loader來轉換。
2、轉換後的文件可以被添加到你的依賴圖中。
const path = require('path');
const config = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [
{test: /\.(js|jsx)$/, use: 'babel-loader'}
]
}
};
module.exports = config;
以上這個配置定義了一個rulues屬性,用以給一個單獨的模塊,這個模塊帶有兩個屬性:test和use。這告訴webpack編譯如下事情:
當使用require()或import語句時,路徑中尾碼名為.js或.jsx的文件,使用babel-loader來轉換並打包。
Plugins
因為載入器只執行基於每個文件的轉換,插件是最常用的(但不限於)優化行為,並且你可以自定義函數在你打包模塊的編輯或塊中(等等)。
該webpack插件系統極其強大,可定製。
為了使用一個插件,你只需要require()並添加到插件數組中。更多插件可通過選項自定義。由於你可以在一個配置中多次使用插件來達到不同的目的,因此你需要創建一個新的實例。
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
const path = require('path');
const config = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [
{test: /\.txt$/, use: 'raw-loader'}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
module.exports = config;
webpack提供有許多開箱插件!可以從我們的插件列表中獲得更多信息。
在webpack配置中使用插件是簡單的,然而有許多用法值得進一步探討。