Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular 4 Universal - SyntaxError: Unexpected token export #1052

Closed
philippeboyd opened this issue Jun 20, 2017 · 76 comments
Closed

Angular 4 Universal - SyntaxError: Unexpected token export #1052

philippeboyd opened this issue Jun 20, 2017 · 76 comments

Comments

@philippeboyd
Copy link

philippeboyd commented Jun 20, 2017

Issue description
I'm unable to start my project in universal mode. However, when executing it in AOT with ng serve, all is well.

Steps to reproduce and a minimal demo of the problem

  1. Clone project https://github.com/philippeboyd/angular-seo
  2. npm install
  3. npm run start

Current behavior
Compiles but server cannot start

$ npm run start

> ang4-seo@0.0.0 prestart /home/philippe/web/angular-seo
> ng build --prod && ngc

Hash: 7d85520031346575c3db                                                              
Time: 24216ms
chunk    {0} polyfills.fdc74e8f101f8a37cfda.bundle.js (polyfills) 160 kB {4} [initial] [rendered]
chunk    {1} main.1765992e8c1c2054a14a.bundle.js (main) 30.1 kB {3} [initial] [rendered]
chunk    {2} styles.d41d8cd98f00b204e980.bundle.css (styles) 69 bytes {4} [initial] [rendered]
chunk    {3} vendor.54e8d36ccd5e25bbf525.bundle.js (vendor) 1.52 MB [initial] [rendered]
chunk    {4} inline.9e599a3566ef53034f50.bundle.js (inline) 0 bytes [entry] [rendered]

> ang4-seo@0.0.0 start /home/philippe/web/angular-seo
> ts-node src/server.ts

/home/philippe/web/angular-seo/node_modules/@agm/core/index.js:2
export * from './directives';
^^^^^^
SyntaxError: Unexpected token export
    at Object.exports.runInThisContext (vm.js:73:16)
    at Module._compile (module.js:543:28)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/home/philippe/web/angular-seo/src/app/app.module.ts:5:1)
    at Module._compile (module.js:571:32)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! ang4-seo@0.0.0 start: `ts-node src/server.ts`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the ang4-seo@0.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

Expected/desired behavior
Server starting without errors

angular2 & angular-google-maps version

  • Angular 4.1.3
  • agm/core 1.0.0-beta.0

Other information
I've looked into issue #668 but it's doesn't seem to be the same issue...

@adrienboulle
Copy link

Hello, I've had to deal with this issue which is not really an Agm issue but a global one.
Most of the recent packages, including Agm are compoiled in es6, with import and export keywords.

This was not an issue before Universal since there is always a bundle file in the packages for lets say System.js for local dev and Webpack/Rollup will understand es6 for production bundles.

But with Universal, you directly use the files in the node_modules, in es6 then, and node do not know about import and export tokens yet.

Two things can be done, you can bundle your app even for universal, but you will lose a lot of compile time juste for a bundle that is useless in a server context.

Other option, the one I used in my company, is to copy all your sources in a tmp folder before compile and create a node_modules folder in this tmp folder.
You can then copy all the @agm folder (the one in the "real" node_module folder in the "fake" one in tmp. You will then be able to use babel to transform the es6 files copied in the fake node_modules folder in commonjs that nodejs will understand. (when you require @agm node will look for the file in the fake node_modules folder)

This is super annoying and there is not really other options for now (let me know if you find a better one). I really think ng2 modules have to find a way to provide both es6 and commonjs files if they want their modules to be easy to use with universal :)

@kkaabbaa
Copy link

kkaabbaa commented Jul 4, 2017

Use webpack.config

externals: [nodeExternals({
    whitelist: [
      /^@agm\/core/,
    ]
})],

@viktorstaikov
Copy link

@kkaabbaa can you confirm that this works?
Simply adding it to my webpack didn't get the job done.

@dannybombastic
Copy link

i have the same problem, i have babel and i did make a copy of the project in a new folder then a have babel locally installed but i would like to understand the process that Adrienboulle he mades for his company because i have to get finis this thing thank you in advance.

@dannybombastic
Copy link

dannybombastic commented Aug 12, 2017

i have add it to webpack.config and it dosen`t work for me.

externals: [nodeExternals({
whitelist: [
/^@agm/core/,
]
})],

@dockleryxk
Copy link

I have it working with a workaround by dynamically loading a component that contains my agm-map based on if it's the browser or server: https://angular.io/guide/dynamic-component-loader

@pravashupreti
Copy link

I have compiled to es5 but also showing error

@pravashupreti
Copy link

Finally able to use google map with universal. I am making repo and video

@kkaabbaa
Copy link

kkaabbaa commented Sep 14, 2017

I used this post https://medium.com/@evertonrobertoauler/angular-4-universal-app-with-angular-cli-db8b53bba07d

and added

externals: [nodeExternals({
    whitelist: [
      /^@agm\/core/,
    ]
})],

@doxuantien
Copy link

@kkaabbaa where did you add, please?

@kkaabbaa
Copy link

My webpack.config.js
https://gist.github.com/kkaabbaa/a308b218938ae55357f73c162e887bd5

@dkmostafa
Copy link

Still not working , i tried @kkaabbaa solution , but didnot worked for me , same issue

@AnthonyNahas
Copy link

AnthonyNahas commented Sep 21, 2017

Updated the solution to the latest version of babel

@philippeboyd @dkmostafa i solved the same issue recently for this module and others like --> ngx translate and more...

solution (compile the js files into es2015):

  1. npm install --save-dev @babel/core @babel/cli @babel/preset-env

  2. add this to the root project under the name .babelrc or add the presets directly via cli
    { "presets": ["@babel/preset-env"] }

  3. add a npm script in package.json in "scrtipsts" scope
    "compile_@agm_core": "babel node_modules/@agm/core -d node_modules/@agm/core --presets @babel/preset-env",

  4. add a postinstall script in package.json in "scrtipsts" scope
    "postinstall": "npm run compile_@agm_core",

  5. run npm i to install the deps. After installing the deps, the script postinstall will run and babel will compile the targeted js files

  6. run your server and should world

  7. Give me please feedback if it works. I did the same thins for more than 3 npm modules it works on my machine :D

@dockleryxk
Copy link

@AnthonyNahas that is a very interesting idea. It seems too good to be true! I'll give it a go

@andrescruz
Copy link

Anyone have a solution for this? Just recently encountered this as well.

@cmddavid
Copy link

@adrienboulle thanks for explaining things, now I wonder: would it not be better to release the package in a different format that is also suitable for Angular Universal? That way all the workarounds circulating here would no longer be needed. Or would it be possible to make Angular Universal understand ES6 code?

@karthikeyanmanureva
Copy link

karthikeyanmanureva commented Oct 3, 2017

@AnthonyNahas I tried that. Now it shows another error

import * as i0 from '@angular/core';
^^^^^^
SyntaxError: Unexpected token import

@martinreus
Copy link

martinreus commented Oct 8, 2017

@AnthonyNahas, thank you so much for your solution! I tried several other solutions that didn't work for me for roughly one month! This actually solves my problem =)

@AnthonyNahas
Copy link

@karthikeyanmanureva u should do the same thing for antoher npm module which is throwing "SyntaxError: Unexpected token import" ...
@martinreus cheers

@cmddavid
Copy link

That means the babel compiler didn't do its job as it would have replaced the imports. Both repos should be available pre compiled in my github. You may use that if you are unable to do the babel part.

@mbrezovsky
Copy link

@AnthonyNahas honestly thanks for your solution, it's working for me with latest version babel and angular 6.

@JunkyDeLuxe
Copy link

@AnthonyNahas

Your are a god my friend ...

@laurentgoudet
Copy link

There is multiple issues preventing that package from being used on the server-side through Angular Universal. I've already did similar work on various libraries (e.g. salemdar/ngx-cookie#41, zefoy/ngx-perfect-scrollbar#129, mattlewis92/angular-resizable-element#80), so I thought I'd have a look.

In short, when targeting the server platform with the Angular CLI only the app itself is compiled, as the library UMD bundle would then be used when running it in NodeJS. As pointed out by @AnthonyNahas, this means that the main package entry point must point to said UMD bundle, i.e. something NodeJS natively understands.

In addition to the NodeJS-native UMD bundle, best practices for libraries as per the Angular Package Format guidelines is to also publish AoT-friendly ES modules and metadata.json metadata files, which that package already does. However, due to angular/angular-cli#7200, the Angular Universal build currently fail (with SyntaxError: Unexpected token export-like errors) when said library is published as separate ES modules instead of a flatten one (fesm), as the deep imports would then resolved to the ES modules causing Node to fail as it doesn't understand ES modules

The fix is to use angularCompilerOptions's flatModuleOutFile & flatModuleId params, as per https://angular.io/guide/aot-compiler, and pass the output through Rollup, in order to produce flat ES module & typings files, and then set those as the module and typings entry points. Since those options require a unique entry point per library, I had to split the main tsconfig.json files in order to support js-marker-clusterer & snazzy-info-window.

In addition, the rollup configs were setting context: 'window', which breaks on the server-side, which I switched back to Rollup's default "this as undefined" behavior (which albeit being a warning, is actually the expected behavior).

Last, now that your app universal build compiles with this library, you need to decide what to do at runtime / make the code itself Universal friendly, which I achieved using isPlatformBrowser(this.platformId) in the Google Maps SDK loader load() function to just skip the injection. It does the trick for our current use case, but most safeguards could be needed in order to disable that library on the server side (since the Google Maps SDK won't run there anyway).

Anyway, the PR is at #1554, comments welcome. I have a fork running at @laurentgoudet/agm-core which I'm successfully using for my project (until this PR gets merged). I'm using the Angular CLI but it should work with any builder - feedback welcome.

@jota12x
Copy link

jota12x commented Dec 13, 2018

After a lot of tries, the solution provided by @AnthonyNahas allowed me to deploy a universal app as a firebase function :) .
My suggestion is to check if the ts files are effectively transformed into js, if they are, then the error about import/export must not appear.

Edit (26/12/2018)
I run to the problem again with the snazzy info window module. I ended up discovering that babel was not running when I was using firebase deploy (Remember that when deploying AU as a firebase function, a npm install is performed, which means that the package will install again as ts files). In the end, I just forked the library(https://github.com/jota12x/angular-google-maps), apply babel, and install it from the repo. Problem solved. (Waiting for the fix in the main repo though).

@stale
Copy link

stale bot commented Mar 26, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Mar 26, 2019
@vytautas-pranskunas-
Copy link

vytautas-pranskunas- commented Apr 1, 2019

Any activity on this? It is quite simple to fix - just need to start using @angular-devkit/build-angular. This is one of most serious problems because people have 2 ways out:

  1. Use custom webpack configs
  2. Use some hacks

and starting use @angular-devkit/build-angular is quite simple and could save hours of hacking

@stale stale bot removed the stale label Apr 1, 2019
@sarayutpea
Copy link

@AnthonyNahas

Updated the solution to the latest version of babel

@philippeboyd @dkmostafa i solved the same issue recently for this module and others like --> ngx translate and more...

solution (compile the js files into es2015):

  1. npm install --save-dev @babel/core @babel/cli @babel/preset-env
  2. add this to the root project under the name .babelrc or add the presets directly via cli
    { "presets": ["@babel/preset-env"] }
  3. add a npm script in package.json in "scrtipsts" scope
    "compile_@agm_core": "babel node_modules/@agm/core -d node_modules/@agm/core --presets @babel/preset-env",
  4. add a postinstall script in package.json in "scrtipsts" scope
    "postinstall": "npm run compile_@agm_core",
  5. run npm i to install the deps. After installing the deps, the script postinstall will run and babel will compile the targeted js files
  6. run your server and should world
  7. Give me please feedback if it works. I did the same thins for more than 3 npm modules it works on my machine :D

Thanks a lot, it's still work on Angular 7

@vytautas-pranskunas-
Copy link

vytautas-pranskunas- commented Apr 2, 2019 via email

@HighSoftWare96
Copy link

I've used the solution of @AnthonyNahas but I'm getting this error:

/node_modules/@agm/core/services/maps-api-loader/maps-api-loader.js:44
        type: _core.Injectable
                    ^

TypeError: Cannot read property 'Injectable' of undefined

@AnthonyNahas
Copy link

@HighSoftWare96 the problem is not related directly to the library... it seems to be a compile error...

@stale
Copy link

stale bot commented Aug 2, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Aug 2, 2019
@ghost ghost removed the stale label Aug 4, 2019
@ghost
Copy link

ghost commented Aug 4, 2019

We are going to move to ngc soon, so hopefully it will work with Angular Universal. Personally, I have 0 experience and knowledge in universal, and AoT.

@ghost
Copy link

ghost commented Aug 12, 2019

Ok, I pulled in ng-packagr PR, so maybe now it will work. Can you try forking master and seeing if it works?

@stale
Copy link

stale bot commented Nov 10, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Nov 10, 2019
@ghost ghost closed this as completed in 7e408e9 Nov 12, 2019
@mehrad-rafigh
Copy link

Hi @doom777
Can you please tell me, when you are planning to release this merge? I would love to drop my patched version of this library :)

@ghost
Copy link

ghost commented Nov 20, 2019

Not up to me

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.