Skip to content
This repository has been archived by the owner on Apr 8, 2020. It is now read-only.

"Cannot find module" error when pre-rendering is on. #244

Closed
astegmaier opened this issue Aug 4, 2016 · 3 comments
Closed

"Cannot find module" error when pre-rendering is on. #244

astegmaier opened this issue Aug 4, 2016 · 3 comments

Comments

@astegmaier
Copy link

astegmaier commented Aug 4, 2016

I'm trying to get server-side-rendering working with a third-party component (wijmo flexgrid), but I'm running into trouble. I'm not sure if this is possible, but I seem to be hitting a very basic error that I think might be a more general problem--either a limitation in asp.net/node or an error on my part.

I can get things working in the Angular2Spa template, so long as I turn off server-side rendering (by removing the asp-prerender-module* tags from Index.cshtml in the template). However, when I turn server-side rendering back on and try to load in the browser, I get this error:

Exception: Call to Node module failed with error: Error: Cannot find module '../../../vendor/node_modules/wijmo/wijmo.angular2.grid'
at Function.Module._resolveFilename (module.js:325:15)

It seems that the following import statement (in ClientApp/components/grid-test/grid-test.component.ts) will resolve fine in the browser, but can't resolve on the server:

import { WjFlexGrid, WjFlexGridColumn } from '../../../vendor/node_modules/wijmo/wijmo.angular2.grid';

Does anyone have any ideas what could cause this type of error? I didn't change anything about load-client.ts or load-server.ts, so it's puzzling.

To see details about exactly what I'm doing, I cloned the template and made a simple repro--see my checkin here: https://github.com/astegmaier/JavaScriptServices/commit/275449c39047630662ec27187210e20591787250

Thanks in advance for any ideas!

@astegmaier
Copy link
Author

astegmaier commented Aug 5, 2016

After banging my head against this more, I think the problem has to do with the issue discussed in #154 Resolve node modules in parent directories. In that thread, @SteveSandersonMS wrote:

the bootstrapping code for "webpack dev middleware" and "prerendering" is embedded into the NuGet packages as string resources, and to execute them in Node, it writes them to temporary files on disk and then gets Node to load them from there.

In my case, the vendor modules I want to include for server-side rendering are not distributed as a normal npm packages (probably because they are not open source). Instead, I'm trying to follow the steps recommended on this thread with the vendor. The key step is to manually copy several .min.jsand .d.ts files into the manually-created <myprojectroot>/node_modules/wijmo folder (including the wijmo.angular2.grid.d.ts and wijmo.angular2.grid.min.js files that I'm trying to import).

Are there any steps I can take to ensure that these files end up being included in the temporary files that "webpack dev middleware" and "prerendering" end up supplying to node? Or a clear way to check whether the absence of these files is indeed the problem?

@astegmaier
Copy link
Author

I tried a few random ideas, and it turned out one of them worked. Before, I was directly referencing the .d.ts files directly through a relative path, like this...

import { WjFlexGrid, WjFlexGridColumn } from '../../../vendor/node_modules/wijmo/wijmo.angular2.grid'

(I put the vendor's wijmo.angular2.grid.d.ts and wijmo.angular2.min.js files in the /vendor/node_modules/wijmo folder, and when it's rendered on the client, the browser (or webpack? or something?) is able to figure out that these go together.

The solution to get the same references working on the server is to create a package.json file that references both the .min.js and the d.ts files...

{
    "name": "wijmo-angular2-grid",
    "author": "Andrew Stegmaier + Wijmo",
    "version": "1.0.0",
    "main": "./wijmo.angular2.grid.min.js",
    "typings": "./wijmo.angular2.grid.d.ts"
}

...and place this in a subdirectory of node_modules (in my case, a folder called node_modules/wijmo.angular2.grid), and then import it into your angular component using node resolution:

import { WjFlexGrid, WjFlexGridColumn } from 'wijmo/wijmo.angular2.grid';

I created a new repo where this part is working. (Unfortunately, it seems that this particular component won't render on the server anyways because it directly references the DOM navigation object, but that is clearly up to the vendor to fix).

This was pure trial-and-error on my part, and I'm still a little unclear as to why referencing through package.json and node resolution works on the server, but direct references to files don't. Is there any documentation that explains what is going on here?

@SteveSandersonMS
Copy link
Member

SteveSandersonMS commented Aug 16, 2016

It's tricky to make sense of exactly what's going on here - from your description it sounds like you're manually organising files and folders into your node_modules directory, which is not something people are supposed to have to do (and I'm not clear how you'd manage that with source control and deployment either). Ideally your vendor-supplied components would be regular NPM packages that conform to NPM/TypeScript conventions, so then it would just be a matter of running npm install --save <vendor_package>. If Wijmo's components aren't supplied as NPM packages that embed their own TypeScript typings correctly then I'd suggest hassling them to sort themselves out (the fact that it isn't OSS doesn't matter - they could make the packages private either with NPM itself or one of many third party services or like this).

Anyway, I'm glad you have a solution. To further clarify, none of this module resolution is ever happening "on the client" - for both server-side and client-side execution, Webpack is compiling your TypeScript code on the server. As for why there's a difference in resolution outcome, it may be that we're running Webpack with different CWD in the two cases - I'll look into this.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants