How to avoid multiple copies of react when both module and project are bundled with webpack 2 - node.js

I have made a module named as services which serves the loading bar, notifications and flash banner etc to other projects. I bundled this module by babel and it was running perfect but as the requirements kept growing for services so i have to bundled this from webpack-2 because of css type issues. I bundled it as a library. But when i uses notifications which are imported from services, it gives such warnings
Uncaught Error: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded
and
index.js:25 Uncaught TypeError: Cannot read property 'componentWillEnter' of undefined
PS: I have already tried resolve.alias and externals properties of webpack but no use :( Any suggestions Please?

Related

In Node.js is it possible to get the loaded source code of an ESM module from its URL?

I am writing a transpiler as an experimental loader hook. Sometimes in the resolve hook I get an error about an import not found. This is sometimes the result of the import specifiers being incorrectly transpiled from the load hook.
When this happens I want to print the source of the transpiled file for debugging.
But in the resolve hook, I only have access to the context.parentURL.
Is there an API to access the module cache and get the source?
Seems there is not currently access to the ESM cache https://github.com/nodejs/help/issues/2806.

Debug compilation errors errors using Angular Universal in Angular 8 Application

A Brief Backstory
I have been implementing several upgrades to an Angular 8 application such as server-side rendering, and Google Analytics. As most developers do, I would code then test then move on to the next task. Typically I use ng serve to run the application as I am developing.
With Server-side rendering, to test speed, lazy-loaded images, etc, you need to use a node express server running on a generated JS file. After building, etc, I use Node prerender (my js file is prerender.js) to see what the application will look like prerendering on the server.
When I run this command, I should not get any errors, and I know my prender file will start a local server on port 4000.
The Problem
I get errors when running a node express server that I do not get when running with ng serve I recently got an error that said:
Unhandled Promise rejection: Cannot read property 'subscribe' of undefined ; Zone: <root> ; Task: Promise.then ; Value: TypeError: Cannot read property 'subscribe' of undefined
at new ApplicationRef (C:\4towerdevelopment\dist-stage\server\main.js:45910:37)
at _createClass (C:\4towerdevelopment\dist-stage\server\main.js:37184:20)
at _createProviderInstance (C:\4towerdevelopment\dist-stage\server\main.js:37138:26)
at initNgModule (C:\4towerdevelopment\dist-stage\server\main.js:37044:32)
at new NgModuleRef_ (C:\4towerdevelopment\dist-stage\server\main.js:38176:9)
at Object.createNgModuleRef (C:\4towerdevelopment\dist-stage\server\main.js:38159:12)
at NgModuleFactory_.create (C:\4towerdevelopment\dist-stage\server\main.js:50821:25)
at C:\4towerdevelopment\dist-stage\prerender.js:29175:43
at ZoneDelegate.invoke (C:\4towerdevelopment\dist-stage\prerender.js:481:26)
at Object.onInvoke (C:\4towerdevelopment\dist-stage\prerender.js:28683:33) TypeError: Cannot read property 'subscribe' of undefined
at new ApplicationRef (C:\4towerdevelopment\dist-stage\server\main.js:45910:37)
at _createClass (C:\4towerdevelopment\dist-stage\server\main.js:37184:20)
at _createProviderInstance (C:\4towerdevelopment\dist-stage\server\main.js:37138:26)
at initNgModule (C:\4towerdevelopment\dist-stage\server\main.js:37044:32)
at new NgModuleRef_ (C:\4towerdevelopment\dist-stage\server\main.js:38176:9)
at Object.createNgModuleRef (C:\4towerdevelopment\dist-stage\server\main.js:38159:12)
at NgModuleFactory_.create (C:\4towerdevelopment\dist-stage\server\main.js:50821:25)
at C:\4towerdevelopment\dist-stage\prerender.js:29175:43
at ZoneDelegate.invoke (C:\4towerdevelopment\dist-stage\prerender.js:481:26)
at Object.onInvoke (C:\4towerdevelopment\dist-stage\prerender.js:28683:33)
The closest this gets me to figuring what actually is causing the problem is letting me know that a provider somewhere is causing this error. Looks like something should be an observable rather than a subscription. Beyond that, I guess I just start looking through my providers. My question is:
How can I force Angular to possibly throw this error when developing using ng serve?
If I can't, is there a better way to debug this current error besides combing through each provider? Or at least a way to tell what service is causing the issue?
Thank you.
UPDATE: Basic repo with problem here. I made a new angular project, made sure dependencies were up to date, installed ngUniversal per this post, and received this same Unhandled promise message when running node prerender
Verbatim I went to to the Angular cli website, made a new project (default Angular version installed was 8.3), installed Angular Universal, and tried to build. Same error message as above.
This looks like it was ApplicationRef that triggered the error, and that class is provided internally by the Angular core.
It could be failing in the constructor of the class, and there are a few calls to subscribe on Zone observables. I don't think you're going to find anything in your source code that directly relates to this error. It looks like a build configuration problem.
https://github.com/angular/angular/blob/bb52fb798c8578c461d21aee2b7623232184a5d3/packages/core/src/application_ref.ts#L562
I do not know what could possibly produce this problem, but I would start a new project with SSR and compare the differences to your current project.
Eventually, I dropped the angular 6 approach using pre-render, and went with the latest universal package. There seems to be no problem building using npm run build:ssr and serving dist/server.js in an express server. I am not sure what the problem was with the pre-render approach, but it seems to be outdated anyways. #Reactgular thanks for the feedback.

Can we still integrate systemjs in Angular 6 and lazy load module without routing

I am trying to lazy load module rather than adding components in entry component because i.e adding overhead to the chunk size. (Also, I don't need routing)
Here is what you need to know about dynamic components in Angular
I have followed the steps mentioned by max in his article.
I came across below error
ERROR in ./node_modules/systemjs/dist/system.src.js
Module not found: Error: Can't resolve 'fs'
After some research, I found that now it's the responsibility of node to provide the 'fs' module And for this, I need to add
"target": "node"
in webpack.config.json. However, Angular 6 has disabled ejecting Webpack.config file anymore.
So, is the lazy loading of module still possible without routing?

Sharing TypeScript classes between client and server

I have a Node.js project written in TypeScript. In my project, I have a folder named "public" which contains the client side code & HTML and also a file named classes.ts which is supposed to be shared to the server side.
The problem is that I need to add "export" before the classes declaration in order to make them accessible in the server, but then in the browser I get this Error:
Uncaught ReferenceError: exports is not defined
I found these questions:
https://github.com/Microsoft/TypeScript/issues/5094,
Setup a Typescript project with classes shared between client and server apps?,
Share module between client and server with TypeScript,
which suggests using commonjs in the server but amd in the client. The problem with this solution is that they have 3 different projects (server, client and shared) whereas I only have one project in which I use commonjs.
Another suggestion is:
the other option, which is more convoluted and will require a post
build step to massage the code; if you can not use module loaders in
your client code, is to isolate all module dependencies in your server
code, then in the shared, they are just classes. Build the shared
files without --module, and no exports or imports, but all inside a
single namespace, say namespace MyApp { ... }; in your client code,
you include them directly, and emit using --out. in your server code,
you first emit the shared code to a single file, shared.js, and a
single .d.ts shared.d.ts, augment these with some code to export them
as a module, e.g. append exports = MyApp at the end of your shared.js
and shared.d.ts, then import them from your server code.
But I don't want to deal with updating .d.ts files all the time, and I'm also not sure it will work in one project.
Any suggestion how to make a TypeScript class accessible both in browser and server?
Any help will be profoundly appreciated!
This is absolutely possible.
I have a project containing both SPA client application that runs in browser and server running in node.js that both share common typescript classes. For all of this I have just one tsconfig.json file (I am still not sure that this is the best approach but for now it works just fine)
Here are parts of my setup:
Use modules (previously called external modules). No need for namespaces and d.ts files for your own modules.
module = "commonjs" in tsconfig.
On client side use System.js as module loader (this will solve your 'Uncaught ReferenceError: exports is not defined'). You can use angular2 5 min quickstart as reference how to setup system.js.
It works like a charm.

tsconfig compilerOptions "module": "system" not working

In the angular2 5 min tutorial they use "system" as the module in the tsconfig. I have systemjs as a node_module but when trying to start my server I get System is not defined, from the first line of the compile js-file which looks like this:
System.register(['http', 'express', './config/index', 'path'], function(exports_1) {
Why is System undefined even though I have it as a node dependency?
I was trying to change it to commonjs, then the compiled js looks much simpler. But then I get errors in the angular application.
What am I missing in order for it to work with SystemJs?
Edit
I think I was bad at explaining my problem. When changing from importing modules into my server.ts file "javascript style" (var http = require('http');) to I guess "typescript style" (import * as http from 'http';) I start getting the error specified above. When doing it javascript style the compiled js looks just the same as the ts (var http = require('http');) however when doing it "typescript style" it gets compiled with modules being imported using System (the line of code specified above). So i'm getting this error when trying to start the node server and not in the browser.
I tried changing the compilerOption "module" to "commonjs" instead of "system" in tsconfig.json, doing that causes errors in the browser (this error, only the solutions doesn't seem to fit) for some weird reason so i figured i'd try with "system". But then I ran into the problem of not have System defined. So how do I get access to System when starting the node server?
It looks like you are missing reference to system.js in your index.html. Angular is meant to be run by browsers so its not enough to have it as node dependency, browser will not load it automatically. And of course do not try to run angular application on server side in node.js. What you want to do on server-side (node.js) is to run some web server that will serve content to the browser (http-server, lite-server, etc). And then open your index.html served by web server in browser that in turn will run angular2 application using system.js for module loading.
If you do have system.js referenced in index.html and you are not trying to run it on node.js server side - make sure the path is correct and it does get loaded - by using development tools of any modern browser.

Resources