【发布时间】:2021-01-07 03:17:16
【问题描述】:
我正在尝试使用自定义 Webpack 配置构建 Angular 库,我在其中指定 externals 设置以从编译输出中排除某些依赖项。一切正常,实际上排除了所有外部因素......除了 PrimeNG!
注意:我使用的是带有自定义构建器ngx-build-plus:browser 的 Angular 8,而不是 ng-packagr,但我想在这种情况下它是无关紧要的。我对其进行了配置,以便它正确构建库。确实如此,除了提到的问题。
我正在使用以下命令运行构建:ng build --extra-webpack-config libs/web-templates/extra-webpack.config.js --project web-templates --single-bundle。
这是我的导入在主库模块中的外观:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { TreeTableModule } from 'primeng/treetable';
import { MultiSelectModule } from 'primeng/multiselect';
我也尝试了不同的路径来导入primeng模块,但没有帮助:
import { TreeTableModule } from 'primeng/components/treetable/treetable';
import { MultiSelectModule } from 'primeng/components/multiselect/multiselect';
在这两种情况下我都使用了这个extra-webpack.config.js:
module.exports = {
output: {
libraryTarget: 'umd' // super-important
},
externals: {
"rxjs": "rxjs",
"rxjs/operators": "rxjs/operators",
"@angular/core": "@angular/core",
"@angular/common": "@angular/common",
"@angular/forms": "@angular/forms",
"@angular/platform-browser": "@angular/platform-browser",
"file-saver": "file-saver",
"lodash": "lodash",
"moment": "moment",
// 1) for the case with longer paths to primeng
"primeng/components/treetable/treetable": "primeng/components/treetable/treetable",
"primeng/components/multiselect/multiselect": "primeng/components/multiselect/multiselect",
// 2) for the case with normal paths to primeng
"primeng/treetable": "primeng/treetable",
"primeng/multiselect": "primeng/multiselect",
// that's just for importing some TypeScript interfaces, not compiled actually, so can be removed
"primeng/api": "primeng/api"
}
};
因此,编译后的输出不包含 @angular/core、rxjs/operators 和除 PrimeNG 之外的所有其他依赖项。例如,这里有一段带有 rxjs/operators 依赖的输出:
/***/ "rxjs/operators":
/*!*********************************!*\
!*** external "rxjs/operators" ***!
\*********************************/
/*! no static exports found */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_rxjs_operators__;
/***/ })
/******/ });
});
就是这样,rxjs 算子成功排除在输出之外,还有 angular 源代码、moment JS 和 lodash。
但是,无论我做什么,primeng TreeTableModule 和 MultiselectModule 都不会发生这种情况。输出包括它们的所有来源。我尝试在 typescript 配置中为它们的路径起别名,尝试使用短路径和完整路径(如上所示)。
我什至尝试过使用相对路径 - 没有变化:
// part of externals config
"../../../../node_modules/primeng/components/treetable/treetable": "../../../../node_modules/primeng/components/treetable/treetable",
"../../../../node_modules/primeng/components/multiselect/multiselect": "../../../../node_modules/primeng/components/multiselect/multiselect",
"node_modules/primeng/components/treetable/treetable": "node_modules/primeng/components/treetable/treetable",
"node_modules/primeng/multiselect": "node_modules/primeng/multiselect",
"node_modules/primeng/treetable": "node_modules/primeng/treetable"
没有其他地方可以导入 PrimeNG。我使用它与 Angular 依赖项完全相同。我认为这可能是因为依赖项名称中的@ 或/ 字符,但相同的设置对于rxjs/operators 非常有效。
我不担心如何将它与主机应用程序集成(我已经成功地做到了),我只担心编译输出。它是 1.5 MB(未缩小),因为它包含大量 PrimeNG 代码。主要问题是:
为什么它对其他依赖项有效,而在完全相同的条件下对 PrimeNG 依赖项无效?
如果相关,这里是上述 webpack 配置的输出文件(UMD 模块)的开头。一个有趣的观察:它包括到primeng组件的完整路径(例如primeng/components/multiselect/multiselect),但不包括像primeng/multiselect这样的短路径,尽管它们也列在webpack外部。但无论如何,primeng 的来源始终存在于输出中。
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("@angular/common"), require("@angular/core"), require("@angular/forms"), require("@angular/platform-browser"), require("file-saver"), require("lodash"), require("moment"), require("primeng/components/multiselect/multiselect"), require("primeng/components/treetable/treetable"), require("rxjs"), require("rxjs/operators"));
else if(typeof define === 'function' && define.amd)
define(["@angular/common", "@angular/core", "@angular/forms", "@angular/platform-browser", "file-saver", "lodash", "moment", "primeng/components/multiselect/multiselect", "primeng/components/treetable/treetable", "rxjs", "rxjs/operators"], factory);
else {
var a = typeof exports === 'object' ? factory(require("@angular/common"), require("@angular/core"), require("@angular/forms"), require("@angular/platform-browser"), require("file-saver"), require("lodash"), require("moment"), require("primeng/components/multiselect/multiselect"), require("primeng/components/treetable/treetable"), require("rxjs"), require("rxjs/operators")) : factory(root["@angular/common"], root["@angular/core"], root["@angular/forms"], root["@angular/platform-browser"], root["file-saver"], root["lodash"], root["moment"], root["primeng/components/multiselect/multiselect"], root["primeng/components/treetable/treetable"], root["rxjs"], root["rxjs/operators"]);
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
})(window, function(__WEBPACK_EXTERNAL_MODULE__angular_common__, __WEBPACK_EXTERNAL_MODULE__angular_core__, __WEBPACK_EXTERNAL_MODULE__angular_forms__, __WEBPACK_EXTERNAL_MODULE__angular_platform_browser__, __WEBPACK_EXTERNAL_MODULE_file_saver__, __WEBPACK_EXTERNAL_MODULE_lodash__, __WEBPACK_EXTERNAL_MODULE_moment__, __WEBPACK_EXTERNAL_MODULE_primeng_components_multiselect_multiselect__, __WEBPACK_EXTERNAL_MODULE_primeng_components_treetable_treetable__, __WEBPACK_EXTERNAL_MODULE_rxjs__, __WEBPACK_EXTERNAL_MODULE_rxjs_operators__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
// ... the rest of the file
更新:
我设法通过在 webpack 配置中使用正则表达式排除了primeng 外部。但这不是很实用。
// webpack config:
externals: [{
// ... my previous externals object
}, /primeng/]
因此,编译后的输出包含以下内容:
else if(typeof define === 'function' && define.amd)
define([
"../../../../../../../node_modules/primeng/components/multiselect/multiselect.ngfactory",
"../../../../../../../node_modules/primeng/components/treetable/treetable.ngfactory",
"@angular/common", "@angular/core", "@angular/forms", "@angular/platform-browser", "file-saver", "lodash", "moment",
"primeng/components/common/shared",
"primeng/components/dropdown/dropdown",
"primeng/components/multiselect/multiselect",
"primeng/components/paginator/paginator",
"primeng/components/tooltip/tooltip",
"primeng/components/treetable/treetable",
"rxjs", "rxjs/operators"], factory);
因此,那里似乎添加了许多其他依赖项:“primeng/components/paginator/paginator”、“primeng/components/tooltip/tooltip”、“../../../../. ./../../node_modules/primeng/components/treetable/treetable.ngfactory”等。宿主应用程序将几乎无法提供这些依赖项(尤其是.ngfactory)...
但为什么会出现所有这些依赖项?在我的源代码中,我只使用primeng/treetable 和primeng/multiselect 导入,没有别的。它是如何工作的,谁能告诉我?
【问题讨论】:
标签: angular webpack external primeng