angular - לא נמצאו מטא-דאטה של NgModule עבור 'AppModule' עם webpack AngularCompilerPlugin
עדכון :
בנוגע ל"שגיאה ב-Error: לא נמצאו מטא-נתונים של NgModule עבור 'AppModule'." אני מאמין שמדובר בבעיה נפרדת, אך למקרה שזה יעזור למישהו. גיליתי שבתנאים מסוימים שכוללים את השימוש ב-AngularCompilerPlugin (שגם כולל את ה-ng cli), שגיאה זו יכולה להתעורר אם אתה מכריז על החלק הרלוונטי של main.ts שלך בדרך הזו:
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
שימו לב שלמרות שהדבר הבא אמור להיות משמעותם זהה במדויק, הדרך הבאה לקרוא ל-bootstrapModule פתרה בעיה זו עבורי בנסיבות מסוימות:
platformBrowserDynamic().bootstrapModule(AppModule);
תקציר
בניית אפליקציית Angular עם Webpack כאשר אפליקציית הכניסה אינה נמצאת באותו תיקייה כמו התקנת Angular, ה-AngularCompilerPlugin נכשל במציאת הדקורטור @NgModule.
גרסאות
Angular CLI: 1.6.3
Node: 8.9.1
OS: darwin x64
Angular: 5.1.3
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, platform-server, router
@angular/cli: 1.6.3
@angular-devkit/build-optimizer: 0.0.36
@angular-devkit/core: 0.0.22
@angular-devkit/schematics: 0.0.42
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.3
@schematics/angular: 0.1.11
@schematics/schematics: 0.0.11
typescript: 2.4.2
webpack: 3.10.0
שלבי שחזור
יש לנו סט של אפליקציות שתלויות בליבת node_modules ו-assets אחרים משותפים. מבנה הקבצים שלנו מאורגן בקירוב באופן הבא:
project
└───app1
│ │ package.json
│ │ tsconfig.json
│ │ ...
│ └───src
│ └───node_modules
└───app2
│ │ package.json
│ │ tsconfig.json
│ │ ...
│ └───src
│ └───node_modules
└───commons
│ │ package.json
│ │ tsconfig.base.json
│ │ ...
│ └───assets
│ └───node_modules
│ └───angular-commons
│ │ tsconfig.json
│ │ CommonModule.ts
│ │ lib.ts
│ │ ...
איפה כל ה-node_modules המשותפים ונכסים נוספים חיים ב-commons, ורק ה-node_modules הייחודיים לאפליקציה מסוימת נמצאים בתיקייה שלה. אנחנו בתהליך של אימוץ Webpack עבור היתרונות הרבים שהוא מביא, ולא האחרון שבהם הוא AngularCompilerPlugin. אני יכול לגרום לבנייה שלנו לעבוד כפי שמצופה כל עוד תתי-המודולים הם תתי-תיקיות של תיקיית הבנייה ותיקיית הבנייה מכילה את כל ה-node_modules המשותפים (למשל Angular). בעוד שזו אפשרות אפשרית, הפתרון המועדף עלינו מאפשר לנו לשמור על מבנה התיקיות הנוכחי שלנו. למרבה הצער, פה אני נתקל בבעיות.
ברגע שתיקיות המשנה עוזבות את שורש תיקיית הבנייה, אני נתקל בבעיות עם AngularCompiler. בהגדרה הנוכחית שלי, אני מקבל את ההודעה הבאה מבניית webpack: ERROR in Error: No NgModule metadata found for 'AppModule'. זה מרמז לי ש-AngularCompiler לא מצליח למצוא בהצלחה את הדקורטור NgModule, כפי שנראה ש-webpack מצליח אחרת ללכת בעץ של היישום. ניסיתי להפנות אותו למיקום הנכון כדי למצוא את NgModule באמצעות האפשרויות mainPath ו-entryModule. זה הביא אותי לבדוק בקפידה את אפשרויות הקונפיגורציה של AngularCompilerPlugin וכן את ההתנהגות הספציפית של הנתיבים ב-TypeScript הן ב-"moduleResolution": "node" והן ב-"moduleResolution": "classic" ולניסוי עם מספר קונפיגורציות ומבני תיקיות שונים. בכל מקרה, המבנה היחיד שעבד נראה היה לעשות את תיקיית הבנייה השורשית כתיקיית השורש עבור @angular וגם עבור האפליקציות שלנו. כדאי לציין כאן שקשייית הציון היכן Angular צריך לחפש את הנתיבים/התלויות שלו היו אותה בעיה שגרמה לנו להתרחק משימוש במקמפל Angular, שלמיטב הבנתי עוטף את Webpack.
ניסיתי לשחזר התנהגות זו במאגר עצמאי, ונקלעתי לסט אחר של בעיות שעשויות להיות קשורות. המאגר חולק כמה דמיון עם הפרויקט שלנו. במצב זה, עם זאת, הבנייה נכשלה ב-app.module.ngfactory, ולא מוצא את @angular/common. על מנת להסיר אי-בהירויות בנתיבים עם רזולוציית מודולים של TypeScript, השתמשתי בייבואות יחסיים ישירות ל-node_modules המתאימים. אני חושד שבעיות הנתיב במאגר הדוגמה הזה קשורות לאלו שאנו רואים בפרויקט שלנו, אף על פי שהן מתבטאות באופן שונה. כל עזרה בפתרון הבעיה תהיה מוערכת מאוד.
git clone --recursive -j8 https://github.com/mscottnelson/ngWebpackCompile.gitcd ngWebpackCompile/commonsnpm installnpm run watch:app1
התנהגות נצפית
ERROR in Error: No NgModule metadata found for 'AppModule'.
at NgModuleResolver.resolve (/Users/me/project/commons/node_modules/@angular/compiler/bundles/compiler.umd.js:20276:23)
at CompileMetadataResolver.getNgModuleMetadata (/Users/me/project/commons/node_modules/@angular/compiler/bundles/compiler.umd.js:15229:60)
at visitLazyRoute (/Users/me/project/commons/node_modules/@angular/compiler/bundles/compiler.umd.js:31090:104)
at AotCompiler.listLazyRoutes (/Users/me/project/commons/node_modules/@angular/compiler/bundles/compiler.umd.js:31058:20)
at AngularCompilerProgram.listLazyRoutes (/Users/me/project/commons/node_modules/@angular/compiler-cli/src/transformers/program.js:156:30)
at Function.NgTools_InternalApi_NG_2.listLazyRoutes (/Users/me/project/commons/node_modules/@angular/compiler-cli/src/ngtools_api.js:44:36)
at AngularCompilerPlugin._getLazyRoutesFromNgtools (/Users/me/project/commons/node_modules/@ngtools/webpack/src/angular_compiler_plugin.js:248:66)
at Promise.resolve.then.then (/Users/me/project/commons/node_modules/@ngtools/webpack/src/angular_compiler_plugin.js:562:50)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
at Function.Module.runMain (module.js:678:11)
at startup (bootstrap_node.js:187:16)
at bootstrap_node.js:608:3
התנהגות רצויה
אפשר לקומפיילר של Angular להיות מוגדר כך שיתקמפל אפליקציות שנמצאות בתיקייה אחרת מהתיקייה שבה מותקן קומפיילר ה-Angular והתלויות שלו.
ציין כל פרט נוסף שעשוי להיות שימושי
אני יכול לבנות ולהפעיל בהצלחה את היישומים באמצעות מבנה תיקיות כמו הבא:
project
└───commons
│ │ package.json
│ │ tsconfig.base.json
│ │ ...
│ └───assets
│ └───node_modules
│ └───angular-commons
│ │ tsconfig.json
│ │ CommonModule.ts
│ │ lib.ts
│ │ ...
│ └───app1
│ │ │ package.json
│ │ │ tsconfig.json
│ │ │ ...
│ │ └───src
│ │ └───node_modules
│ └───app2
│ │ │ package.json
│ │ │ tsconfig.json
│ │ │ ...
│ │ └───src
│ │ └───node_modules