enten / udk

Universal Development Kit: Webpack extension which improves universal application development. - THE UDK PROJECT SUPPORT IS CURRENTLY SUSPENDED.
MIT License
29 stars 7 forks source link

"Module not found: Error: Can't resolve" when using import with index.ts file. #5

Closed sinedsem closed 6 years ago

sinedsem commented 6 years ago

Issue reproduces only on Windows. Lunix and Mac OS works fine.

Trying to build project from https://github.com/Stivin/angular-universal 1) Clone project. 2) npm install 3) npm run dev

Result:

ERROR in /C/Source/angular-universal/src/app/shared/layout/toolbar/toolbar-lang/toolbar-lang.component.ts
Module not found: Error: Can't resolve '../../../translate' in '/C/Source/angular-universal/src/app/shared/layout/toolbar/toolbar-lang'

Broken line: import { TranslateService } from './translate'; Works fine: import { TranslateService } from './translate/index'; or import {TranslateService} from './translate/translate.service';

Can you please have a look?

Sumbitting issue here because I got no errors when building via ng cli commands.

enten commented 6 years ago

I would like to investigate, but I haven't Windows.

But, I don't understand how ng cli can works but not the udk builder: because under the hood, udk schematic builder use the ng cli schematics builders.

We already hit that kind of issue: 30827d16.

In our experience, that kind of issue is thrown when you manipulate angular-devkit paths whithout its API : its functions build paths according to the execution platform. Doesn't use it create paths which don't work on windows (as your issue).

As I said, udk use ng cli schematic builders. So, normally: it should not have an error.

Can you share the entire error stack trace? (Error.stackTraceLimit = Infinity)

sinedsem commented 6 years ago

Can you share the entire error stack trace?

TBH, I am not sure how to do this.

Can you also teach me how to correctly build that using ng, not udk?

enten commented 6 years ago

Normally, just add instruction Error.stackTraceLimit = Infinity in your main entry files main.browser.ts and main.server.ts.

sinedsem commented 6 years ago

@enten , no additional stack trace =(

PS C:\Source\angular-universal> npm run dev

> ng-universal@6.0.0 dev C:\Source\angular-universal
> ng-udkc

[udk] > bootstrap container
[udk] >> container up
[udk] >>> prepare webpack config
[udk] >>> prepare webpack compiler
[udk] >>> compiler done
[udk] >>> compiler watching...
Child: browser
  Date: 2018-07-14T10:38:53.293Z
  Hash: d8a70defc18e20dc7ece
  Time: 10037ms
  chunk {auth-auth-module} auth-auth-module.js, auth-auth-module.js.map (auth-auth-module) 21.4 kB  [rendered]
  chunk {back-back-module} back-back-module.js, back-back-module.js.map (back-back-module) 7.29 kB  [rendered]
  chunk {guide-guide-module} guide-guide-module.js, guide-guide-module.js.map (guide-guide-module) 7.05 kB  [rendered]
  chunk {home-home-module} home-home-module.js, home-home-module.js.map (home-home-module) 8.42 kB  [rendered]
  chunk {main} main.js, main.js.map (main) 297 kB [initial] [rendered]
  chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 250 kB [initial] [rendered]
  chunk {runtime} runtime.js, runtime.js.map (runtime) 33.3 kB [entry] [rendered]
  chunk {styles} styles.js, styles.js.map (styles) 17.1 kB [initial] [rendered]
  chunk {vendor} vendor.js, vendor.js.map (vendor) 7.13 MB [initial] [rendered]
Child: server
  Date: 2018-07-14T10:38:53.297Z
  Hash: 187021443fafef353a81
  Time: 7331ms
  chunk {main} main.js (main) 505 kB [entry] [rendered]
  chunk {ngmodule} ngmodule.js (ngmodule) 483 kB [entry] [rendered]

ERROR in /C/Source/angular-universal/src/app/shared/layout/toolbar/toolbar-lang/toolbar-lang.component.ts
Module not found: Error: Can't resolve '../../../translate' in '/C/Source/angular-universal/src/app/shared/layout/toolbar/toolbar-lang'
ERROR in /C/Source/angular-universal/src/app/shared/core.module.ts
Module not found: Error: Can't resolve './translate' in '/C/Source/angular-universal/src/app/shared'
enten commented 6 years ago

@sinedsem :laughing:

Okay. I saw that your repository isn't up to date with angular-universal boilerplate and the latest angular-devkit.

I made the update. And I spotted that angular-devkit v0.7.0-rc.1 break the udk schematic builder :disappointed:.

That means udk schematic builder isn't ready for the next Angular major v7.

So I updated udk and release v0.3.15 to be compatible with the latest angular-devit v0.7.0-rc.2.

I used your repository to test if it works with devkit 0.7.0-rc.1 and 0.7.0-rc.2.

May the latest angular-devkit toolchain will fix your issue.

Can you apply the patch below on your repository and run npm install and npm run dev and finally share the output?

diff --git a/angular.json b/angular.json
index 40ba7f3..543edcc 100644
--- a/angular.json
+++ b/angular.json
@@ -73,7 +73,7 @@
           "builder": "@angular-devkit/build-angular:server",
           "options": {
             "outputPath": "dist/server",
-            "main": "src/app/ngmodule.ts",
+            "main": "src/main.server.ts",
             "tsConfig": "src/tsconfig.server.json"
           },
           "configurations": {
@@ -91,7 +91,6 @@
         "udk": {
           "builder": "udk:udk-builder",
           "options": {
-            "main": "src/main.server.ts",
             "browserTarget": "ng-universal:build",
             "serverTarget": "ng-universal:server"
           },
diff --git a/package.json b/package.json
index 9c9df3f..550cfd7 100644
--- a/package.json
+++ b/package.json
@@ -40,13 +40,14 @@
     "zone.js": "0.8.26"
   },
   "devDependencies": {
-    "@angular-devkit/build-angular": "0.6.0",
-    "@angular/cli": "6.0.0",
+    "@angular-devkit/build-angular": "0.7.0-rc.2",
+    "@angular/cli": "6.1.0-rc.2",
     "@angular/compiler-cli": "6.0.0",
     "@angular/language-service": "6.0.0",
     "@angular/platform-server": "6.0.0",
     "@angularclass/hmr": "2.1.3",
     "@types/node": "10.0.6",
+    "@types/webpack-env": "1.13.6",
     "codelyzer": "4.3.0",
     "express": "4.16.3",
     "http-server": "0.11.1",
@@ -54,6 +55,6 @@
     "ts-loader": "4.3.0",
     "tslint": "5.10.0",
     "typescript": "2.7.2",
-    "udk": "0.3.11"
+    "udk": "0.3.15"
   }
 }
diff --git a/src/app.ts b/src/app.ts
index 94358d0..bdf358b 100644
--- a/src/app.ts
+++ b/src/app.ts
@@ -1,53 +1,26 @@
-import { join } from 'path';
-import { readFileSync } from 'fs';
-
-import { renderModuleFactory } from '@angular/platform-server';
-import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
-import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
+import { ngExpressEngine, NgSetupOptions } from '@nguniversal/express-engine';

 import * as express from 'express';
 import * as compression from 'compression';
 import * as cookieParser from 'cookie-parser';

-// NOTE: leave this as require() since this file is built Dynamically from webpack
-const { AppServerModule, AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./app/ngmodule');
-
-// Express server
-export const app = express();
-app.use(compression());
-app.use(cookieParser());
+export function createApp(distPath: string, ngSetupOptions: NgSetupOptions) {
+  // Express server
+  const app = express();
+  app.use(compression());
+  app.use(cookieParser());

-const DIST_BROWSER_FOLDER: string = join(process.cwd(), 'dist', 'browser');
-const INDEX_HTML_PATH: string = join(DIST_BROWSER_FOLDER, 'index.html');
-const INDEX_HTML: string = readFileSync(INDEX_HTML_PATH).toString();
+  app.set('view engine', 'html');
+  app.set('views', distPath);

-app.engine('html', (_, options, callback) => {
-  renderModuleFactory(AppServerModuleNgFactory || AppServerModule, {
-    document: INDEX_HTML,
-    url: options.req.url,
-    extraProviders: [
-      provideModuleMap(LAZY_MODULE_MAP),
-      { provide: REQUEST, useValue: options.req },
-      { provide: RESPONSE, useValue: options.res },
-    ]
-  }).then(html => {
-    callback(null, html);
-  });
-});
+  // Angular Express Engine
+  app.engine('html', ngExpressEngine(ngSetupOptions));

-app.set('view engine', 'html');
-app.set('views', DIST_BROWSER_FOLDER);
+  // Server static files from distPath
+  app.get('*.*', express.static(distPath));

-// Server static files from /browser
-app.get('*.*', express.static(DIST_BROWSER_FOLDER));
+  // All regular routes use the Universal engine
+  app.get('*', (req, res) => res.render('index', { req, res }));

-// All regular routes use the Universal engine
-app.get('*', (req, res) => {
-  res.render(INDEX_HTML_PATH, {
-    req, res,
-    providers: [
-      { provide: REQUEST, useValue: (req) },
-      { provide: RESPONSE, useValue: (res) },
-    ],
-  });
-});
+  return app;
+}
diff --git a/src/main.server.ts b/src/main.server.ts
index 4fdbcfb..6c0895e 100644
--- a/src/main.server.ts
+++ b/src/main.server.ts
@@ -3,31 +3,63 @@ import 'zone.js/dist/zone-node';
 import 'reflect-metadata';

 import { createServer, IncomingMessage, Server, ServerResponse } from 'http';
+import { join } from 'path';

 import { enableProdMode } from '@angular/core';
+import { MODULE_MAP } from '@nguniversal/module-map-ngfactory-loader';

-import { app } from './app';
+import { createApp } from './app';

-// Faster server renders w/ Prod mode (dev mode never needed)
-enableProdMode();
+// DO NOT REMOVE THIS INSTRUCTION!
+export { AppServerModule } from './app/app.server.module';

 const PORT: number | string = process.env.PORT || 4000;
+export const BROWSER_DIST_PATH: string = join(__dirname, '..', 'browser');
+
+export const getNgRenderMiddlewareOptions = () => ({
+  bootstrap: exports.AppServerModuleNgFactory,
+  providers: [
+    // Import module map for lazy loading
+    {
+      provide: MODULE_MAP,
+      useFactory: () => exports.LAZY_MODULE_MAP,
+      deps: []
+    }
+  ]
+});

-let requestListener: (req, res) => void = app;
+// Faster server renders w/ Prod mode (dev mode never needed)
+enableProdMode();
+
+let requestListener: (req, res) => void = createApp(BROWSER_DIST_PATH, getNgRenderMiddlewareOptions());

 // Start up the Node server
 const server: Server = createServer((req: IncomingMessage, res: ServerResponse) => {
-  requestListener(req, res);
+    requestListener(req, res);
 });

 server.listen(PORT, () => {
   console.log(`Server is listening on ${PORT}`);
 });

-if (module['hot']) {
-  module['hot'].accept('./app', () => {
-    requestListener = require('./app').app;
-  });
+// HMR on server side
+if (module.hot) {
+  const hmr = () => {
+    const { AppServerModuleNgFactory } = require('./app/app.server.module.ngfactory');
+
+    exports.AppServerModuleNgFactory = AppServerModuleNgFactory;
+
+    requestListener = require('./app').createApp(BROWSER_DIST_PATH, getNgRenderMiddlewareOptions());
+  };
+
+  module.hot.accept('./app', hmr);
+
+  // add all lazy module.ngfactory here to made hmr works
+  module.hot.accept('./app/app.server.module.ngfactory.js', hmr);
+  module.hot.accept('./app/+auth/auth.module.ngfactory.js', hmr);
+  module.hot.accept('./app/+back/back.module.ngfactory.js', hmr);
+  module.hot.accept('./app/+guide/guide.module.ngfactory.js', hmr);
+  module.hot.accept('./app/+home/home.module.ngfactory.js', hmr);
 }

 export default server;
diff --git a/src/typings.d.ts b/src/typings.d.ts
new file mode 100644
index 0000000..06e7310
--- /dev/null
+++ b/src/typings.d.ts
@@ -0,0 +1 @@
+///<reference types="webpack-env" />
sinedsem commented 6 years ago

@enten I can confirm this works. I will try to understand what did you do tomorrow and leave additional comment.

I also got warning in prod build, but not sure if it is important:

WARNING in ./node_modules/express/lib/view.js
81:13-25 Critical dependency: the request of a dependency is an expression
enten commented 6 years ago

@sinedsem
If your issue is solved: can you close this ticket?

About the warning:

It's important to display that kind of warning (it can be a source of issues). But in your project, it's note important (and note an issue).

I recommand to not bundle all package dependencies on production: is it better to install them on production (there is a tons of reasons for that the first is: node.js already have a native dependency resolver, it's the function require).

sinedsem commented 6 years ago

@enten I think you helped a lot and this can be close. I will ask @Stivin to look into this.