如何在其他项目复用编译后的Angular4公共组件?遇样式及调用错误求助
Hey,我来帮你解决这个问题!你尝试把Angular 4的公共组件库引入到其他管理系统中,遇到了加载报错和样式丢失的问题,这其实是因为Angular默认的生产构建是为单页应用设计的,不是为了导出可复用的组件库,下面是具体的排查和解决步骤:
1. 调整Angular构建配置,生成可复用的UMD包
Angular CLI默认的ng build --prod会把应用拆分成多个bundle,这是为了单页应用的懒加载优化,但不适合作为组件库对外暴露。你需要修改配置,生成UMD格式的可复用包:
- 对于Angular 4,找到项目根目录的
.angular-cli.json,在apps数组里修改构建选项:{ "apps": [ { "root": "src", "outDir": "./dist-library", "main": "./src/public_api.ts", "deployUrl": "./", "outputHashing": "none", "vendorChunk": false, "commonChunk": false, "extractCss": true, "buildOptimizer": false } ] } - 创建
src/public_api.ts文件,专门导出你需要对外提供的组件和模块:// 替换成你实际的组件/模块路径 export * from './app/components/your-shared-component/your-shared-component.component'; export * from './app/modules/common-components/common-components.module'; - 重新执行构建命令:
ng build --prod --target=production,此时dist-library目录会生成UMD格式的包(比如main.bundle.js,或者命名更清晰的common-components.umd.js),这个包可以被其他框架正确识别。
2. 修复"Uncaught TypeError: Cannot read property 'call' of undefined"错误
这个报错大概率是bundle加载顺序错误,或者引入了不必要的Angular内部bundle导致的:
- 不要直接引入所有拆分的bundle,只需要引入构建后生成的UMD主包,它会自动处理依赖加载顺序。
- 如果必须使用拆分bundle,严格按照以下顺序引入:
polyfills.xxx.bundle.js(Angular运行的基础依赖,必须第一个加载)vendor.xxx.bundle.js(包含Angular核心库等第三方依赖)main.xxx.bundle.js(你的公共组件库代码)
注意:不要引入
inline.xxx.bundle.js和scripts.xxx.bundle.js,前者是Angular CLI的内部引导代码,不适合外部环境,后者是你项目中自定义的全局脚本,若不需要可以跳过。
3. 解决样式不显示的问题
Angular组件默认开启样式封装,构建后样式不会自动全局生效,你可以通过以下方式处理:
- 确保构建时开启了样式提取:上面的配置中已经设置了
"extractCss": true,构建后会生成styles.xxx.bundle.css,在管理系统的index.html中用<link rel="stylesheet" href="你的CSS文件路径/styles.xxx.bundle.css">引入即可。 - 如果你的组件使用了
ViewEncapsulation.None,可以手动把组件的样式文件复制到管理系统的静态资源目录,直接引入到页面中。
4. 手动引导Angular组件到页面
即使正确加载了JS和CSS,你还需要手动初始化Angular模块,让它挂载到页面的DOM元素上:
- 在管理系统的
index.html中添加公共组件库的根组件选择器,比如:<div id="common-components-container"> <app-shared-root></app-shared-root> </div> - 在加载完Angular的UMD包后,添加一段初始化代码:
或者如果是用拆分bundle,确保代码在所有Angular依赖加载完成后执行(比如放在// 假设你的模块叫CommonComponentsModule,从UMD包的全局对象中获取 const { platformBrowserDynamic, CommonComponentsModule } = window.CommonComponents; platformBrowserDynamic().bootstrapModule(CommonComponentsModule);window.onload事件中)。
内容的提问来源于stack exchange,提问作者will
相关产品推荐
相关产品推荐

