小編給大家分享一下Angular10怎么配置webpack打包,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
對于 Angular 項目,推薦使用 angular-cli 創建打包項目 Angular 會默認幫我們配置。
但是有特殊的需求時就顯然不是很靈活,比如想分割一些較大的打包文件、分析每個打包文件組成,自定義webpack一些參數的時候就發現無從下手。
對許多項目的常見依賴項是日期庫moment.js
。 這包括使用語言環境的功能,但是,它大大增加了整體捆綁軟件的大小。這些都是需要我們優化的地方。
這里推薦一個工具庫ngx-build-plus,不需要改很多東西就能在現有項目進行集成。接下來教大家如何使用,具體詳情可以去github上找文檔。雖然官方文檔上只標注到了可用版本為9,但是Angular10也是可以使用的。
從零搭建Angular10項目
ng add ngx-build-plus
注意:如果要將其添加到projects
文件夾中的特定子項目,請使用--project
開關指向它:ng add ngx-build-plus --project getting-started
備注:這一步通過NPM安裝包,在Angular >= 7 and CLI >= 7版本中,讓您的項目使用自定義生成器的更新您的angular.jsonng serve
和ng build
。但是6版本中可能會出現安裝不成功,這時候請直接yarn add ngx-build-plus --dev
,然后angular.json
文件中更改以下兩處地方:
"build": { - "builder": "@angular-devkit/build-angular:browser" + "builder": "ngx-build-plus:build" ... }, "serve": { - "builder": "@angular-devkit/build-angular:dev-server" + "builder": "ngx-build-plus:dev-server" ... }
相關教程推薦:《angular教程》
webpack.partial.js
并添加到(子)項目的根目錄:const webpack = require('webpack'); module.exports = { plugins: [ new webpack.DefinePlugin({ "VERSION": JSON.stringify("4711") }) ] }
app.component.ts
中使用全局變量VERSION:import { Component } from '@angular/core'; declare const VERSION: string; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'Version: ' + VERSION; }
--extra-webpack-config
指向部分Webpack配置的開關啟動應用程序:ng serve --extra-webpack-config webpack.partial.js -o
如果您的項目是基于CLI的子項目,請也使用該--project
開關:
ng serve --project getting-started -o --extra-webpack-config webpack.partial.js
提示:考慮為此命令創建一個npm腳本。
有打印結果顯示就表示你的項目已經啟用了
webpack.partial.js
文件中的配置,下面就是在webpack.partial.js
中補充我們需要的功能了,筆者主要集中在了兩大塊。
添加BundleAnalyzerPlugin,分析打包文件
第三方庫模塊分離 - optimization + splitChunks,分割較大的文件
下面分別描述
$ yarn add webpack-bundle-analyzer --dev
在webpack.partial.js
中的module.exports = webpackConfig
這句話的上面增加
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin module.exports = { plugins: [ new BundleAnalyzerPlugin({ analyzerMode: 'static', }), new webpack.DefinePlugin({ "VERSION": JSON.stringify("4711") }) ] }
啟動服務:
生產環境查看:npm run build --report
或 正常build 即可啟動查看器
開發環境查看:webpack -p --progress
或啟動正常devServer服務即可啟動查看器!
new BundleAnalyzerPlugin({ // openAnalyzer: true, // reportFilename: path.join(__dirname, 'report.html') // 可以是`server`,`static`或`disabled`。 // 在`server`模式下,分析器將啟動HTTP服務器來顯示軟件包報告。 // 在“靜態”模式下,會生成帶有報告的單個HTML文件。 // 在`disabled`模式下,你可以使用這個插件來將`generateStatsFile`設置為`true`來生成Webpack Stats JSON文件。 analyzerMode: 'static', // 將在“服務器”模式下使用的主機啟動HTTP服務器。 // analyzerHost: '127.0.0.1', // 將在“服務器”模式下使用的端口啟動HTTP服務器。 // analyzerPort: 8888, // 路徑捆綁,將在`static`模式下生成的報告文件。 // 相對于捆綁輸出目錄。 // reportFilename: 'report.html', // 模塊大小默認顯示在報告中。 // 應該是`stat`,`parsed`或者`gzip`中的一個。 // 有關更多信息,請參見“定義”一節。 // defaultSizes: 'parsed', // 在默認瀏覽器中自動打開報告 // openAnalyzer: true, // 如果為true,則Webpack Stats JSON文件將在bundle輸出目錄中生成 // generateStatsFile: false, // 如果`generateStatsFile`為`true`,將會生成Webpack Stats JSON文件的名字。 // 相對于捆綁輸出目錄。 // statsFilename: 'stats.json', // stats.toJson()方法的選項。 // 例如,您可以使用`source:false`選項排除統計文件中模塊的來源。 // 在這里查看更多選項:https: //github.com/webpack/webpack/blob/webpack-1/lib/Stats.js#L21 // statsOptions: null, // logLevel: 'info' // 日志級別??梢允?#39;信息','警告','錯誤'或'沉默'。 }),
模塊功能:能夠查看到你的文件打包壓縮后中真正的內容,找出那些模塊組成最大的大小,找到錯誤的模塊,優化它!最好的事情是它支持縮小捆綁!它解析它們以獲得實際大小的捆綁模塊。它也顯示他們的gzipped大??!
在 webpack4.x 中,我們使用 optimization.splitChunks 來分離公用的代碼塊。SplitChunks插件簡單的來說就是Webpack中一個提取或分離代碼的插件,主要作用是提取公共代碼,防止代碼被重復打包,拆分過大的js文件,合并零散的js文件。
這里說的分離,當然只是針對一些第三方庫(一般來自 node_modules),以及我們自己定義的工具庫(或公用方法)。
不知如何下手?首先,我們來看官網給的一份
splitChunks: { chunks: "async", minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } }
接著,我們再來看下它們的含義:
chunks: 該屬性值的數據類型可以是 字符串 或者 函數。如果是字符串,那它的值可能為 initial | async | all 三者之一。默認值的數據類型為 字符串,默認值為 async,但推薦用 all。它表示將哪種類型的模塊分離成新文件。字符串參數值的作用分別如下:
initial:表示對異步引入的模塊不處理
async:表示只處理異步模塊
all:無論同步還是異步,都會處理
minSize: 該屬性值的數據類型為數字。它表示將引用模塊分離成新代碼文件的最小體積,默認為 30000,單位為字節,即 30K(指min+gzip之前的體積)。這里的 30K 應該是最佳實踐,因為如果引用模塊小于 30K 就分離成一個新代碼文件,那頁面打開時,勢必會多增加一個請求。
maxSize: 把提取出來的模塊打包生成的文件大小不能超過maxSize值,如果超過了,要對其進行分割并打包生成新的文件。單位為字節,默認為0,表示不限制大小。
minChunks: 該屬性值的數據類型為數字。它表示將引用模塊如不同文件引用了多少次,才能分離生成新代碼文件。默認值為 1
maxAsyncRequests: 該屬性值的數據類型為數字,默認值為 5。它表示按需加載最大的并行請求數,針對異步。
maxInitialRequests: 該屬性值的數據類型為數字,默認值為 3。它表示單個入口文件最大的并行請求數,針對同步。
automaticNameDelimiter: 該屬性值的數據類型為字符串,默認值為。它表示分離后生成新代碼文件名稱的鏈接符,比如說 app1.js 和 app2.js 都引用了 utils.js 這個工具庫,那么,最后打包后分離生成的公用文件名可能是 xxapp1~app2.js 這樣的,即以 ~ 符號連接。
name: 該屬性值的數據類型可以是 布爾值 或者 函數(返回值為字符串),其中布爾值得為 true,此時,分離文件后生成的文件名將基于 cacheGroups 和 automaticNameDelimiter。如果設置為 false,則不會進行模塊分離。
cacheGroups: 該屬性值的數據類型為對象,它的值可以繼承 splitChunks.* 中的內容。如果 cacheGroups存在與 splitChunks.* 同名的屬性,則 cacheGroups 的屬性值則直接覆蓋 splitChunks.* 中設置的值。
test: 該屬性值的數據類型可以為 字符串 或 正則表達式,它規定了哪些文件目錄的模塊可以被分離生成新文件。
priority: 該屬性值的數據類型可以為數字,默認值為 0。它表示打包分離文件的優先
reuseExistingChunk: 該屬性值的數據類型可以為布爾值。它表示針對已經分離的模塊,不再重新分離。
要將第三方庫分離出來,我們需要調整配置文件,設置 chunks: 'all'
,即表示讓所有加載類型的模塊在某些條件下都能打包。
打包中,我們發現,工具函數模塊(utils)的源碼被分別打包到了兩個文件中,這顯然是不對。之所以出現這種情況,是因為我們設置了 minSize: 30000,即分離成獨立文件的最小體積為 30K,而這里的 工具函數(utils.js)只有幾KB,所以,沒被分離成單獨的文件。
有的時候,我們希望將所有來自 node_modules 的第三方庫都打包到同一個文件中。顯然,上面的打包配置并沒有滿足這個條件。并且,我們還希望可以對打包后的文件名進行重命名。
要完成,只需要在 cacheGroups 設置 name 屬性即可。這里,筆者還把項目中使用到的moment
、handsontable
、angular
庫單獨分離出來了。
// webpack.config.js module.exports = { optimization: { splitChunks: { chunks: 'all', minSize: 30000, maxSize: 0, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { moment: { name: 'moment', test: /[\\/]node_modules[\\/]moment[\\/]/, priority: -6 // 兩個cacheGroup.priority相同時,先定義的會先命中 }, handsontable: { name: 'handsontable', test: /[\\/]node_modules[\\/]handsontable[\\/]/, priority: -7 }, angular: { name: 'angular', test: /[\\/]node_modules[\\/]@angular[\\/]/, priority: -9 }, vendors: { name: 'vendors', test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { name: 'default', minChunks: 2, priority: -20, reuseExistingChunk: true } } } } }
chunks
選項,決定要提取那些模塊。
默認是async
:只提取異步加載的模塊出來打包到一個文件中。
異步加載的模塊:通過import('xxx')
或require(['xxx'],() =>{})
加載的模塊。
initial
:提取同步加載和異步加載模塊,如果xxx在項目中異步加載了,也同步加載了,那么xxx這個模塊會被提取兩次,分別打包到不同的文件中。
同步加載的模塊:通過 import xxx
或require('xxx')
加載的模塊。
all
:不管異步加載還是同步加載的模塊都提取出來,打包到一個文件中。
minSize
選項:規定被提取的模塊在壓縮前的大小最小值,單位為字節,默認為30000,只有超過了30000字節才會被提取。
maxSize
選項:把提取出來的模塊打包生成的文件大小不能超過maxSize值,如果超過了,要對其進行分割并打包生成新的文件。單位為字節,默認為0,表示不限制大小。
minChunks
選項:表示要被提取的模塊最小被引用次數,引用次數超過或等于minChunks值,才能被提取。
maxAsyncRequests
選項:最大的按需(異步)加載次數,默認為 6。
maxInitialRequests
選項:打包后的入口文件加載時,還能同時加載js文件的數量(包括入口文件),默認為4。
先說一下優先級 maxInitialRequests
/ maxAsyncRequests
<maxSize
<minSize
。
automaticNameDelimiter
選項:打包生成的js文件名的分割符,默認為~
。
name
選項:打包生成js文件的名稱。
cacheGroups
選項,核心重點,配置提取模塊的方案。里面每一項代表一個提取模塊的方案。下面是cacheGroups
每項中特有的選項,其余選項和外面一致,若cacheGroups
每項中有,就按配置的,沒有就使用外面配置的。
test
選項:用來匹配要提取的模塊的資源路徑或名稱。值是正則或函數。
priority
選項:方案的優先級,值越大表示提取模塊時優先采用此方案。默認值為0。
reuseExistingChunk
選項:true
/false
。為true
時,如果當前要提取的模塊,在已經在打包生成的js文件中存在,則將重用該模塊,而不是把當前要提取的模塊打包生成新的js文件。
enforce
選項:true
/false
。為true
時,忽略minSize
,minChunks
,maxAsyncRequests
和maxInitialRequests
外面選項
HtmlWebpackPlugin
簡化了HTML文件的創建,以便為你的webpack包提供服務。這對于在文件名中包含每次會隨著編譯而發生變化哈希的 webpack bundle 尤其有用。 你可以讓插件為你生成一個HTML文件,這個插件有兩個重要作用。
創建HTML頁面文件到你的輸出目錄
將webpack打包后的chunk自動引入到這個HTML中
npm install --save-dev html-webpack-plugin
使用yarn
yarn add --dev html-webpack-plugin
該插件將為你生成一個 HTML5 文件, 其中包括使用 script
標簽的 body 中的所有 webpack 包。 只需添加插件到你的 webpack 配置如下:
const HtmlWebpackPlugin = require('html-webpack-plugin') const path = require('path') module.exports = { plugins: [ new webpack.DefinePlugin({ "VERSION": JSON.stringify("4711") }), new HtmlWebpackPlugin({ filename: 'index.html', // 根據模板文件生成的html的文件名 template: path.join(__dirname, 'src/index.html'), chunksSortMode: 'manual', chunks: ['styles', 'runtime', 'polyfills', 'scripts', 'vendors', 'main'] }) ] }
這將會產生一個包含以下內容的文件 dist/index.html
:
<!doctype html> <html> <head> <meta charset="utf-8"> <meta http-equiv="Pragma" content="no-cache"/> <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"/> <meta http-equiv="Expires" content="0"/> <meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="renderer" content="webkit"> <meta name="force-rendering" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> <title>test</title> <base href="/"> <link rel="icon" type="image/png" href="favicon.png"> <link href="styles.bf72314ba2e0c15c73f2.css" rel="stylesheet"> </head> <body> <app-root></app-root> <div id="preloader"> <div> <div class="loader loader--glisteningWindow"></div> </div> </div> <script src="runtime.fe0efdd131eb00c21b3a.js"></script> <script src="vendors.6d9d661339fe7a583752.js"></script> <script src="polyfills.5cb77843a9758f0097e1.js"></script> <script src="scripts.d526d9658102820143d1.js"></script> <script src="moment.65d799ec0675b5ff9b59.js"></script> <script src="handsontable.c50df86ef38503e832a5.js"></script> <script src="main.db888715d5d02500d39e.js"></script> </body> </html>
如果你有多個 webpack 入口點, 他們都會在生成的HTML文件中的 script
標簽內。
需要注意的是,默認angular-cli打包生成的入口文件也被配置成了index.html,所以我們需要更改angular.jaon
文件中的配置。并且,由于Angular單頁面應用的入口文件為main.ts
所以!chunks配置中,main 一定一定要放在最后,否則運行會出錯,筆者因為沒有放在最后找了一晚上的bug~~
改為:
您可以將配置選項的哈希值傳遞給html-webpack-plugin
。允許的值如下:
名稱 | 類型 | 默認 | 描述 |
---|---|---|---|
title | {String} | Webpack App | 用于生成的HTML文檔的標題 |
filename | {String} | 'index.html' | 將HTML寫入的文件。默認為index.html 。您可以在這里指定一個子目錄(如:assets/admin.html ) |
template | {String} | `` | webpack 模板的相對或絕對路徑。默認情況下,它將使用(src/index.ejs 如果存在)。請參閱文檔以了解詳細信息 |
templateContent | {string、Function、false} | false | 可用于代替template 提供內聯模板-請閱讀“編寫自己的模板”部分 |
templateParameters | {Boolean、Object、Function} | false | 允許覆蓋模板中使用的參數-請參見示例 |
inject | {Boolean、String} | true | `true |
publicPath | {String、'auto'} | 'auto' | 用于腳本和鏈接標簽的publicPath |
scriptLoading | {'blocking'、'defer'} | 'blocking' | 現代瀏覽器支持非阻塞javascript加載('defer' ),以提高頁面啟動性能。 |
favicon | {String} | `` | 將給定的圖標圖標路徑添加到輸出HTML |
meta | {Object} | {} | 允許注入meta -tags。例如meta: {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'} |
base | {Object、String、false} | false | 注入base 標簽。例如base: "https://example.com/path/page.html |
minify | {Boolean、Object} | true 如果mode 是'production' ,否則false | 控制是否以及以何種方式最小化輸出。有關更多詳細信息,請參見下面的縮小。 |
hash | {Boolean} | false | 如果是,true 則將唯一的webpack 編譯哈希值附加到所有包含的腳本和CSS文件中。這對于清除緩存很有用 |
cache | {Boolean} | true | 僅在文件被更改時發出文件 |
showErrors | {Boolean} | true | 錯誤詳細信息將寫入HTML頁面 |
chunks | {?} | ? | 僅允許您添加一些塊(例如,僅單元測試塊) |
chunksSortMode | {String、Function} | auto | 允許控制在將塊包含到HTML中之前應如何對其進行排序。允許值為`'none' |
excludeChunks | {Array.<string>} | `` | 允許您跳過一些塊(例如,不添加單元測試塊) |
xhtml | {Boolean} | false | 如果true 將link 標簽呈現為自動關閉(符合XHTML) |
最后奉上完整的webpack.partial.js
const webpack = require('webpack') const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin const HtmlWebpackPlugin = require('html-webpack-plugin') const path = require('path') module.exports = { externals: { // 打包除外的文件 echarts: 'echarts' }, optimization: { splitChunks: { chunks: "all", minSize: 20000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { moment: { name: 'moment', test: /[\\/]node_modules[\\/]moment[\\/]/, priority: -6 }, handsontable: { name: 'handsontable', test: /[\\/]node_modules[\\/]handsontable[\\/]/, priority: -7 }, angular: { name: 'angular', test: /[\\/]node_modules[\\/]@angular[\\/]/, priority: -9 }, vendors: { name: 'vendors', test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { name: 'default', minChunks: 2, priority: -20, reuseExistingChunk: true } } } }, plugins: [ new BundleAnalyzerPlugin({ analyzerMode: 'static', }), new webpack.DefinePlugin({ "VERSION": JSON.stringify("4711") }), new HtmlWebpackPlugin({ filename: 'index.html', template: path.join(__dirname, 'src/index.html'), chunksSortMode: 'manual', chunks: ['styles', 'runtime', 'polyfills', 'scripts', 'vendors', 'main'] // 限定順序,main.js必須在最后 }) ] }
以上是“Angular10怎么配置webpack打包”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。