如何根据Angular构建目标(而非环境)增删文件或代码?
针对Angular构建目标(ES5/ES6)动态排除依赖库的通用方案
你遇到的这个场景真的很常见——当需要同时维护ES5(兼容IE)和ES6(现代浏览器)两种构建目标时,总有一些现代库的语法或依赖的API会在IE里出问题,nosleep.js就是典型例子(它依赖的视频唤醒逻辑IE根本不支持,就算转译代码也没用)。先给你一个快速解决nosleep的临时办法,再讲通用的按构建目标调整的方案。
一、快速解决nosleep.js的IE兼容问题
既然nosleep.js在IE里本来就无法正常工作,不如直接在IE环境下跳过这个功能。你可以在服务里加个浏览器检测逻辑:
@Injectable({ providedIn: "root" }) export class NoSleepService { noSleepEnabled = false; constructor() { } // 检测是否是IE浏览器 private isIE(): boolean { return /Trident|MSIE/.test(window.navigator.userAgent); } enable() { if(!this.noSleepEnabled && !this.isIE()) { // IE下直接跳过启用逻辑 const noSleep = require('nosleep.js'); const noSleepObject = new noSleep(); this.noSleepEnabled = true; noSleepObject.noSleepVideo.muted = true; noSleepObject.enable(); console.log("Enabled nosleep", noSleepObject); } } }
二、通用方案:根据angular.json的构建目标动态调整构建内容
要实现“ES5构建时排除特定库,ES6构建时保留”,可以从两个方向入手:
方案1:利用TypeScript条件编译 + 单独的ES5 tsconfig
这个方案不需要额外依赖,用Angular原生的配置就能实现:
- 在
angular.json中给你的ES5构建配置指定单独的tsconfig文件,比如tsconfig.es5.json:
{ "projects": { "your-app-name": { "architect": { "build": { "configurations": { "dev-es5": { "tsConfig": "./tsconfig.es5.json", "target": "es5", // 其他ES5开发配置(比如polyfills) }, "prod-es5": { "tsConfig": "./tsconfig.es5.json", "target": "es5", // 其他ES5生产配置 } } } } } } }
- 在
tsconfig.es5.json中添加自定义编译常量ES5_BUILD:
{ "extends": "./tsconfig.json", "compilerOptions": { "target": "es5", "define": { "ES5_BUILD": true } } }
(如果你的Angular版本不支持直接在tsconfig里加define,可以改用下面的webpack方案)
- 在你的服务里用条件编译注释排除ES5构建时的代码:
@Injectable({ providedIn: "root" }) export class NoSleepService { noSleepEnabled = false; constructor() { } enable() { if(!this.noSleepEnabled) { // 仅非ES5构建时执行这段代码 #ifndef ES5_BUILD const noSleep = require('nosleep.js'); const noSleepObject = new noSleep(); this.noSleepEnabled = true; noSleepObject.noSleepVideo.muted = true; noSleepObject.enable(); console.log("Enabled nosleep", noSleepObject); #endif } } }
当你用ES5配置构建时,TypeScript编译器会自动删掉#ifndef ES5_BUILD块内的代码,nosleep.js也就不会被打包进去了。
方案2:扩展Webpack配置,用IgnorePlugin排除依赖
如果条件编译不满足你的需求,可以通过自定义Webpack配置来直接排除目标库:
- 先安装扩展Webpack的工具:
npm install @angular-builders/custom-webpack --save-dev
- 修改
angular.json,改用custom-webpack builder,并指定自定义配置文件:
{ "projects": { "your-app-name": { "architect": { "build": { "builder": "@angular-builders/custom-webpack:browser", "options": { "customWebpackConfig": { "path": "./webpack.custom.js" }, // 其他默认构建配置 }, "configurations": { "dev-es5": { "target": "es5", // 其他ES5开发配置 }, "prod-es5": { "target": "es5", // 其他ES5生产配置 }, "dev-es6": { "target": "es2015", // 其他ES6开发配置 }, "prod-es6": { "target": "es2015", // 其他ES6生产配置 } } } } } } }
- 创建
webpack.custom.js,根据构建target添加IgnorePlugin:
const webpack = require('webpack'); module.exports = (config, options) => { // 判断当前构建目标是否为ES5 if (options.target === 'es5') { // 排除nosleep.js config.plugins.push( new webpack.IgnorePlugin({ resourceRegExp: /nosleep\.js$/ }) ); } return config; };
同样,记得在你的服务里加条件判断(比如浏览器检测或编译常量),避免ES5构建时执行相关代码,不然代码里的require还是会抛出错误。
最后补充一句:如果某个库本身可以被转译为ES5,你可以在tsconfig里调整include或downlevelIteration等配置,但像nosleep.js这种依赖IE不支持的API的库,排除才是最稳妥的方案。
内容的提问来源于stack exchange,提问作者Arsenii Fomin
相关产品推荐
相关产品推荐

