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?1.1.11", // 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?1.1.11", ".json", ".jsx", ".css?1.1.11"], // 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?1.1.11"), // alias "module" -> "./app/third/module.js?1.1.11" 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) */ }
本文檔的目的就是要提供這些概念一個高階的大綱,同時提供連結給詳細概念的指定用例。
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' } };
一旦你打包所有程式碼,你仍需要告訴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配置中有兩個目的:
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來轉換並打包。
更多設定項
因為載入器只執行基於每個檔案的轉換,外掛程式是最常用的(但不限於)優化行為,而你可以自訂函數在你打包模組的編輯或區塊中(等等)。
此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;
以上是webpack打包器的簡單介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!