今天小編給大家分享一下Angular13+開發(fā)模式太慢如何解決的相關(guān)知識點,內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
創(chuàng)新互聯(lián)建站是一家專業(yè)提供庫倫企業(yè)網(wǎng)站建設(shè),專注與做網(wǎng)站、成都做網(wǎng)站、H5建站、小程序制作等業(yè)務(wù)。10年已為庫倫眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進(jìn)行中。
近期在某個高頻迭代七年的 Angular 項目升級至 Angular 13 后,其開發(fā)模式的構(gòu)建速度慢、資源占用高,開發(fā)體驗相當(dāng)差。在一臺僅在開會時偶爾使用的 Macbook air
(近期居家辦公期間轉(zhuǎn)換為了主要生產(chǎn)力工具) 中啟動構(gòu)建時,它的風(fēng)扇會呼呼作響,CPU 負(fù)荷被打滿,而在構(gòu)建完成后,熱更新一次的時間在一分鐘以上。
在經(jīng)過各種原因分析與排查后,最終在 angular.json
的 schema(./node_modules/@angular/cli/lib/config/schema.json
) 中發(fā)現(xiàn)了問題,再結(jié)合 Angular 12 release 文檔定位到了具體原因: Angular 12 一個主要的改動是將 aot
、buildOptimizer
、optimization
等參數(shù)由默認(rèn)值 false
改為了 true
。
A number of browser and server builder options have had their default values changed. The aim of these changes is to reduce the configuration complexity and support the new "production builds by default" initiative.
可以看到 Angular 12 后的默認(rèn)生產(chǎn)模式,對于跨版本升級來說是比較坑爹的。
解決辦法則是在 development
配置中禁用生產(chǎn)模式相關(guān)的配置項。示例:
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"projects": {
"front": {
"architect": {
"build": {
"configurations": {
"development": {
"tsConfig": "./tsconfig.dev.json",
"aot": false,
"buildOptimizer": false,
"optimization": false,
"extractLicenses": false,
"sourceMap": true,
"vendorChunk": true,
"namedChunks": true
}
}
},
}
},
"defaultProject": "front"
}
需注意 aot
開啟與關(guān)閉時,在構(gòu)建結(jié)果表現(xiàn)上可能會有一些差異,需視具體問題而分析。
aot
后 pug
編譯報錯該項目中使用 pug
開發(fā) html 內(nèi)容。關(guān)閉 aot
時構(gòu)建正常,開啟后則會報錯。
根據(jù)報錯內(nèi)容及位置進(jìn)行 debugger 調(diào)試,可以看到其編譯結(jié)果為一個 esModule 的對象。這是由于使用了 raw-loader
,其編譯結(jié)果默認(rèn)為 esModule
模式,禁用 esModule
配置項即可。示例(自定義 webpack 配置可參考下文的 dll 配置相關(guān)示例):
{
test: /\.pug$/,
use: [
{
loader: 'raw-loader',
options: {
esModule: false,
},
},
{
loader: 'pug-html-loader',
options: {
doctype: 'html',
},
},
],
},
該項目項目構(gòu)建上有自定義 webpack
配置的需求,使用了 @angular-builders/custom-webpack
庫實現(xiàn),但是沒有配置 dll。
Angular
提供了 vendorChunk
參數(shù),開啟它會提取在 package.json
中的依賴等公共資源至獨立 chunk 中,其可以很好的解決熱更新 bundles 過大導(dǎo)致熱更新太慢等的問題,但仍然存在較高的內(nèi)存占用,而且實際的對比測試中,在存在 webpack5 緩存的情況下,其相比 dll 模式的構(gòu)建編譯速度以及熱更新速度都稍微慢一些。故對于開發(fā)機(jī)器性能一般的情況下,給開發(fā)模式配置 dll 是會帶來一定的收益的。
首先需要配置自定義 webpack 配置的構(gòu)建支持。執(zhí)行如下命令添加依賴:
npm i -D @angular-builders/custom-webpack
修改 angluar.json
配置。內(nèi)容格式參考:
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"cli": {
"analytics": false,
"cache": {
"path": "node_modules/.cache/ng"
}
},
"version": 1,
"newProjectRoot": "projects",
"projects": {
"front": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"prefix": "app",
"schematics": {
"@schematics/angular:component": {
"style": "less"
}
},
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./webpack.config.js"
},
"indexTransform": "scripts/index-html-transform.js",
"outputHashing": "media",
"deleteOutputPath": true,
"watch": true,
"sourceMap": false,
"outputPath": "dist/dev",
"index": "src/index.html",
"main": "src/app-main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "./tsconfig.app.json",
"baseHref": "./",
"assets": [
"src/assets/",
{
"glob": "**/*",
"input": "./node_modules/@ant-design/icons-angular/src/inline-svg/",
"output": "/assets/"
}
],
"styles": [
"node_modules/angular-tree-component/dist/angular-tree-component.css",
"src/css/index.less"
],
"scripts": []
},
"configurations": {
"development": {
"tsConfig": "./tsconfig.dev.json",
"buildOptimizer": false,
"optimization": false,
"aot": false,
"extractLicenses": false,
"sourceMap": true,
"vendorChunk": true,
"namedChunks": true,
"scripts": [
{
"inject": true,
"input": "./dist/dll/dll.js",
"bundleName": "dll_library"
}
]
},
"production": {
"outputPath": "dist/prod",
"baseHref": "./",
"watch": false,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": {
"scripts": true,
"styles": {
"minify": true,
"inlineCritical": false
},
"fonts": true
},
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": false,
"vendorChunk": false,
"buildOptimizer": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"browserTarget": "front:build",
"liveReload": false,
"open": false,
"host": "0.0.0.0",
"port": 3002,
"servePath": "/",
"publicHost": "localhost.gf.com.cn",
"proxyConfig": "config/ngcli-proxy-config.js",
"disableHostCheck": true
},
"configurations": {
"production": {
"browserTarget": "front:build:production"
},
"development": {
"browserTarget": "front:build:development"
}
},
"defaultConfiguration": "development"
},
"test": {
"builder": "@angular-builders/custom-webpack:karma",
"options": {
"customWebpackConfig": {
"path": "./webpack.test.config.js"
},
"indexTransform": "scripts/index-html-transform.js",
"main": "src/ngtest.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "./tsconfig.spec.json",
"karmaConfig": "./karma.conf.js",
"assets": [
"src/assets/",
{
"glob": "**/*",
"input": "./node_modules/@ant-design/icons-angular/src/inline-svg/",
"output": "/assets/"
}
],
"styles": [
"node_modules/angular-tree-component/dist/angular-tree-component.css",
"src/css/index.less"
],
"scripts": []
}
}
}
}
},
"defaultProject": "front",
"schematics": {
"@schematics/angular:module": {
"routing": true,
"spec": false
},
"@schematics/angular:component": {
"flat": false,
"inlineStyle": true,
"inlineTemplate": false
}
}
}
該示例中涉及多處自定義配置內(nèi)容,主要需注意 webpack 相關(guān)的部分, 其他內(nèi)容可視自身項目具體情況對比參考。
新建 webpack.config.js
文件。內(nèi)容參考:
const { existsSync } = require('node:fs');
const { resolve } = require('node:path');
const webpack = require('webpack');
// require('events').EventEmitter.defaultMaxListeners = 0;
/**
* @param {import('webpack').Configuration} config
* @param {import('@angular-builders/custom-webpack').CustomWebpackBrowserSchema} options
* @param {import('@angular-builders/custom-webpack').TargetOptions} targetOptions
*/
module.exports = (config, options, targetOptions) => {
if (!config.devServer) config.devServer = {};
config.plugins.push(
new webpack.DefinePlugin({ LZWME_DEV: config.mode === 'development' }),
);
const dllDir = resolve(__dirname, './dist/dll');
if (
existsSync(dllDir) &&
config.mode === 'development' &&
options.scripts?.some((d) => d.bundleName === 'dll_library')
) {
console.log('use dll:', dllDir);
config.plugins.unshift(
new webpack.DllReferencePlugin({
manifest: require(resolve(dllDir, 'dll-manifest.json')),
context: __dirname,
})
);
}
config.module.rules = config.module.rules.filter((d) => {
if (d.test instanceof RegExp) {
// 使用 less,移除 sass/stylus loader
return !(d.test.test('x.sass') || d.test.test('x.scss') || d.test.test('x.styl'));
}
return true;
});
config.module.rules.unshift(
{
test: /\.pug$/,
use: [
{
loader: 'raw-loader',
options: {
esModule: false,
},
},
{
loader: 'pug-html-loader',
options: {
doctype: 'html',
},
},
],
},
{
test: /\.html$/,
loader: 'raw-loader',
exclude: [helpers.root('src/index.html')],
},
{
test: /\.svg$/,
loader: 'raw-loader',
},
{
test: /\.(t|les)s/,
loader: require.resolve('@lzwme/strip-loader'),
exclude: /node_modules/,
options: {
disabled: config.mode !== 'production',
},
}
);
// AngularWebpackPlugin,用于自定義 index.html 處理插件
const awPlugin = config.plugins.find((p) => p.options?.hasOwnProperty('directTemplateLoading'));
if (awPlugin) awPlugin.pluginOptions.directTemplateLoading = false;
// 兼容上古遺傳邏輯,禁用部分插件
config.plugins = config.plugins.filter((plugin) => {
const pluginName = plugin.constructor.name;
if (/CircularDependency|CommonJsUsageWarnPlugin/.test(pluginName)) {
console.log('[webpack][plugin] disabled: ', pluginName);
return false;
}
return true;
});
// console.log('[webpack][config]', config.mode, config, options, targetOptions);
return config;
};
新建 webpack.dll.mjs
文件,用于 dll 構(gòu)建。內(nèi)容示例:
import { join } from 'node:path';
import webpack from 'webpack';
const rootDir = process.cwd();
const isDev = process.argv.slice(2).includes('--dev') || process.env.NODE_ENV === 'development';
/** @type {import('webpack').Configuration} */
const config = {
context: rootDir,
mode: isDev ? 'development' : 'production',
entry: {
dll: [
'@angular/common',
'@angular/core',
'@angular/forms',
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/router',
'@lzwme/asmd-calc',
// more...
],
},
output: {
path: join(rootDir, 'dist/dll'),
filename: 'dll.js',
library: '[name]_library',
},
plugins: [
new webpack.DllPlugin({
path: join(rootDir, 'dist/dll/[name]-manifest.json'),
name: '[name]_library',
}),
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/,
}),
],
cache: { type: 'filesystem' },
};
webpack(config).run((err, result) => {
console.log(err ? `Failed!` : `Success!`, err || `${result.endTime - result.startTime}ms`);
});
在 angular.json
中添加 dll.js 文件的注入配置,可參考前文示例中 development.scripts
中的配置內(nèi)容格式。
在 package.json
中增加啟動腳本配置。示例:
{
"scripts": {
"ng:serve": "node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve",
"dll": "node config/webpack.dll.mjs",
"dev": "npm run dll -- --dev && npm run ng:serve -- -c development",
}
}
最后,可執(zhí)行 npm run dev
測試效果是否符合預(yù)期。
以上就是“Angular13+開發(fā)模式太慢如何解決”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
文章標(biāo)題:Angular13+開發(fā)模式太慢如何解決
文章鏈接:http://aaarwkj.com/article34/gjjdpe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、小程序開發(fā)、網(wǎng)站改版、網(wǎng)頁設(shè)計公司、電子商務(wù)、網(wǎng)站內(nèi)鏈
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)