webpack是一個現代javascript應用程序的模塊打包器。javascript
當webpack處理你的應用程序時,它會遞歸構建一個依賴圖(包含了你的應用程序所須要每一個模塊),而後把這些模塊打包到少數幾個budle文件中(一般是隻有一個,會被瀏覽器加載,根據項目狀況而定)。css
這是使人難以置信的配置,但開始前,你只須要明白四個核心概念:entry、output、loaders、和plugins。html
配置對象選項
webpack.config.jsjava
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) */ }
本文檔的目的是給這些概念提供一個高層次的大綱,同時提供連接給詳細概念的指定用例。node
webpack會建立一個你全部應用程序的依賴圖。這個依賴圖的起始點就是已知的entry(入口)點。這個入口點告訴webpack從哪開始,而且根據已知依賴圖進行打包。你能夠把應用程序的入口點看成上下文根或啓動你的應用程序的第一個文件。react
在webpack配置對象的entry屬性中定義入口點。簡單示例以下:jquery
module.exports = { entry: './path/to/my/entry/file.js' };
有幾種方式聲明entry屬性:webpack
一、單個entry語法web
const config = { entry: './path/to/my/entry/file.js' }; module.exports = config;
二、對象語法express
const config = { entry: { app: './src/app.js', vendors: './src/vendors.js' } };
三、多頁面應用
const config = { entry: { pageOne: './src/pageOne/index.js', pageTwo: './src/pageTwo/index.js', pageThree: './src/pageThree/index.js' } };
一旦你打包全部代碼,你仍須要告訴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打包的文件名和路徑
這個配置項的目的是讓webpack關注你項目的全部代碼而非瀏覽器(這並不意味着它們會被打包到一塊兒)。webpack把每個文件(.css, .html, .scss, .jpg, etc.)做爲一個模塊。然而,webpack只知道javascript。
webpack中的Loaders會轉換這些文件到模塊中,並添加到你的依賴圖中。
在一個較高的水平,在你的webpack配置中有兩個目的:
一、標識什麼文件應該用一個肯定的loader來轉換。
二、轉換後的文件能夠被添加到你的依賴圖中。
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來轉換並打包。
由於加載器只執行基於每一個文件的轉換,插件是最經常使用的(但不限於)優化行爲,而且你能夠自定義函數在你打包模塊的編輯或塊中(等等)。
該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配置中使用插件是簡單的,然而有許多用法值得進一步探討。
var path = require('path'); var webpack = require('webpack'); var env = process.env.NODE_DEV; var config = { entry: { consumer: './consumer/index.js', admin: './admin/index.js', // jquery: ['jquery'] }, output: { path: path.resolve(__dirname, 'dist'), publicPath: '/dist/', filename: '[name].bundle.js' }, module: { loaders: [ { test: /\.css$/, loader: 'style-loader!css-loader' }, { test: /\.less$/, loader: 'less-loader!style-loader!css-loader' }, { test: /\.sass$/, loader: 'sass-loader!style-loader!css-loader' }, { test: /\.(woff|woff2|eot|ttf|otf)$/i, loader: 'url-loader?limit=8192&name=[name].[ext]' }, { test: /\.(jpe?g|png|gif|svg)$/i, loader: 'url-loader?limit=8192&name=[name].[ext]' }, { test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/, include: __dirname, options: { presets: ['es2015', 'react'] }, }, { test: /\.tsx?$/, loader: 'ts-loader', exclude: /node_modules/, include: __dirname }, { test: /\.coffee$/, loader: 'coffee-loader', exclude: /node_modules/, include: __dirname } ] }, //devtool: 'source-map', //指定根路徑 context: __dirname, //這裏枚舉的後綴名,在require時能夠省略 resolve: { extensions: ['.js', '.jsx', '.json', '.ts', '.tsx', '.css'] }, plugins: [ // 這裏聲明的變量是全局的,能夠在全部的js中使用,能夠避免寫一堆的require new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery', 'window.$': 'jquery', 'React': 'react', 'ReactDOM': 'react-dom' }), // new webpack.optimize.CommonsChunkPlugin({ // // 與 entry 中的 jquery 對應 // name: 'jquery', // // 輸出的公共資源名稱 // filename: 'jquery.min.js', // // 對全部entry實行這個規則 // minChunks: Infinity // }), // new webpack.NoEmitOnErrorsPlugin() ], //在html頁面中使用script標籤引入庫,而不是打包到*.bundle.js文件中 externals: { jquery: 'jQuery', react: 'React', 'react-dom' : 'ReactDOM' } }; //若是是生產環境,要最小化壓縮js文件 if (env === 'production') { //打包時對js文件進行最小化壓縮 config.plugins.push(new webpack.optimize.UglifyJsPlugin({ mangle: { except: ['$super', '$', 'exports', 'require'] //以上變量‘$super’, ‘$’, ‘exports’ or ‘require’,不會被混淆 }, compress: { warnings: false } })); //消除壓縮後的文件在界面引用時發出的警告 config.plugins.push(new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify('production') } })); } module.exports = config;