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

SyntaxError: Unexpected token export #67

Closed
carsonreinke opened this issue Dec 9, 2019 · 29 comments
Closed

SyntaxError: Unexpected token export #67

carsonreinke opened this issue Dec 9, 2019 · 29 comments

Comments

@carsonreinke
Copy link

Using the example with Node v8.15.0 produces the error SyntaxError: Unexpected token export
at node_modules/extract-loader/lib/extractLoader.js:81:28.

The line 81 is trying to parse the source:

module.exports = "<!DOCTYPE html>\n<html>\n    <head>\n        <link rel=\"style\" href=\"" + require("./index.css") + "\">\n    </head>\n    <body>\n              <img src=\"" + require("./images/desk.svg") + "\">\n        <script src=\"index.js\"></script>\n    </body>\n</html>";
export default __webpack_public_path__ + "c58ff9d72352b98461e9b50bc7a28553.svg";
exports = module.exports = require("../node_modules/css-loader/dist/runtime/api.js")(true);
// Module
exports.push([module.id, "body {\n    font-size: 1em;\n}", "",{"version":3,"sources":["index.css"],"names":[],"mappings":"AAAA;IACI,cAAc;AAClB","file":"index.css","sourcesContent":["body {\n    font-size: 1em;\n}"]}]);

export default __webpack_public_path__ + "01f1344ea069d644fc25b1b869447810.css";

Here is the full stack:

Module build failed (from ./node_modules/extract-loader/lib/extractLoader.js):
[snip]/src/images/desk.svg:1
export default __webpack_public_path__ + "c58ff9d72352b98461e9b50bc7a28553.svg";
^^^^^^

SyntaxError: Unexpected token export
    at [snip]/node_modules/extract-loader/lib/extractLoader.js:81:28
    at Generator.next (<anonymous>)
    at step ([snip]/node_modules/babel-runtime/helpers/asyncToGenerator.js:17:30)
    at [snip]/node_modules/babel-runtime/helpers/asyncToGenerator.js:35:14
    at new Promise (<anonymous>)
    at new F ([snip]/node_modules/core-js/library/modules/_export.js:36:28)
    at [snip]/node_modules/babel-runtime/helpers/asyncToGenerator.js:14:12
    at evalModule ([snip]/node_modules/extract-loader/lib/extractLoader.js:150:63)
    at [snip]/node_modules/extract-loader/lib/extractLoader.js:138:28
    at Generator.next (<anonymous>)
    at step ([snip]/node_modules/babel-runtime/helpers/asyncToGenerator.js:17:30)
    at [snip]/node_modules/babel-runtime/helpers/asyncToGenerator.js:28:13
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:189:7)
 @ multi ./src/index.js ./src/index.html main[1]
@stassribnyi
Copy link

I believe it's related to file-loader also.

I've encountered the same issue with file-loader of version 5.2.0, so I rolled back to version 4.3.0 and it works like a charm, still didn't try [5.0.0, 5.1.0], so not sure which version starts causing a problem.

@carsonreinke
Copy link
Author

@stassribnyi correct sir, downgrading fixed the issue. When I look at the source being provided, it is ES5 instead of ES6. I believe an adjustment to this project could help too.

module.exports = "<!DOCTYPE html>\n<html>\n    <head>\n        <link rel=\"style\" href=\"" + require("./index.css") + "\">\n    </head>\n    <body>\n        <img src=\"" + require("./images/desk.svg") + "\">\n        <script src=\"index.js\"></script>\n    </body>\n</html>";
module.exports = __webpack_public_path__ + "c58ff9d72352b98461e9b50bc7a28553.svg";
exports = module.exports = require("../node_modules/css-loader/dist/runtime/api.js")(true);
// Module
exports.push([module.id, "body {\n    font-size: 1em;\n}", "",{"version":3,"sources":["index.css"],"names":[],"mappings":"AAAA;IACI,cAAc;AAClB","file":"index.css","sourcesContent":["body {\n    font-size: 1em;\n}"]}]);

module.exports = __webpack_public_path__ + "01f1344ea069d644fc25b1b869447810.css";

@carsonreinke
Copy link
Author

Looking at solving this. The issue is simple VM (just like CLI) for Node will not interpret ES6 import/export statements. Copying and pasting the code ES6 code above will produce an error on any Node CLI versions.

One solution would to have Babel transform this, since there is already an odd dependency on babel-runtime 6.

Another would be to write the script to file and run it and extract the data. I like something like this better because it would potentially remove a dependency and locking people on Babel 6.

@cybercase
Copy link

cybercase commented Dec 23, 2019

I bumped into this issue too.
Looking at the file-loader changelog for v 5.0.0 here I read they've switched to ES modules by default.
To restore the pre-version-5 behaviour now we need to explicitly disable the ES modules, by setting esModule: false into the file-loader's options.
I just wonder how it's working fine for them

@carsonreinke
Copy link
Author

@cybercase yes, looks like that is an option https://github.com/webpack-contrib/file-loader#esmodule.

@LZQCN
Copy link

LZQCN commented Jan 6, 2020

content.replace(/export default/g, "module.exports =")

Maybe it's useful to insert this code in the right place.
The question is where to insert it?

@carsonreinke
Copy link
Author

@LZQCN are you suggesting instead of Babel just using this regex? Is it that simple?

@cybercase
Copy link

cybercase commented Jan 7, 2020

@carsonreinke To deal with the new file-loader version, yes, it would be that simple. However, there's a past PR ( #26 ) where the maintainer already discussed a fix of this kind, and expressed the willing to use babel for proper transpilation, so I've opened a PR ( #69 ) to handle es modules using babel.
I'm waiting for feedback from @jhnns

@pbowyer
Copy link

pbowyer commented Jan 10, 2020

After too many hours trying to work out why my Webpack config kept failing, I am very glad to have found this issue.

ERROR in ./src/test.html
Module build failed (from ./node_modules/extract-loader/lib/extractLoader.js):
D:\projects\src\images\london.jpg:1
export default __webpack_public_path__ + "dda88ae5192fe238f8384d1c0a2143db.jpg";
^^^^^^

SyntaxError: Unexpected token export
    at new Script (vm.js:79:7)
    at D:\projects\node_modules\extract-loader\lib\extractLoader.js:81:28
    at Generator.next (<anonymous>)
    at step (D:\projects\node_modules\babel-runtime\helpers\asyncToGenerator.js:17:30)
    at D:\projects\node_modules\babel-runtime\helpers\asyncToGenerator.js:35:14
    at new Promise (<anonymous>)
    at new F (D:\projects\node_modules\babel-runtime\node_modules\core-js\library\modules\_export.js:36:28)
    at D:\projects\node_modules\babel-runtime\helpers\asyncToGenerator.js:14:12
    at evalModule (D:\projects\node_modules\extract-loader\lib\extractLoader.js:150:63)
    at D:\projects\node_modules\extract-loader\lib\extractLoader.js:138:28
    at Generator.next (<anonymous>)
    at step (D:\projects\node_modules\babel-runtime\helpers\asyncToGenerator.js:17:30)
    at D:\projects\node_modules\babel-runtime\helpers\asyncToGenerator.js:28:13
    at process._tickCallback (internal/process/next_tick.js:68:7)
 @ ./src/js/app.js 8:0-23
error Command failed with exit code 2.

Rolling back to [email protected] fixed the problem for me

@jhnns
Copy link
Member

jhnns commented Jan 27, 2020

Thanks for reporting ❤️. We're working on this (and other) issues.

@rodrigoyoshida
Copy link

rodrigoyoshida commented Feb 9, 2020

Same here, unfortunately the esModule: false option did not work for me. Rolling back to [email protected] fixed the problem for me as well.

@cybercase
Copy link

@rodrigoyoshida I don't know the exact version of the file-loader you were using before, but I've found that they fixed a typo in v. 5.0.1 about the name of esModule option. webpack-contrib/file-loader#346
Maybe updating to the latest version could make the esModule: false option work?

@carsonreinke
Copy link
Author

@thequailman
Copy link

Still seeing this with 5.0.2, I think:

ERROR in   Error: Child compilation failed:
  Module build failed (from ./node_modules/extract-loader/lib/extractLoader.js):
  /home/thequailman/Code/app/ui/src/images/icon-192.png:1
  export default __webpack_public_path__ + "ui/icon-192.c017b0bc34d9b6470c9020563ba18fdb.png";
  ^^^^^^
  SyntaxError: Unexpected token export
  
  - extractLoader.js:98 
    [ui]/[extract-loader]/lib/extractLoader.js:98:28
  
  - Generator.next
  
  - asyncToGenerator.js:17 step
    [ui]/[babel-runtime]/helpers/asyncToGenerator.js:17:30
  
  - asyncToGenerator.js:35 
    [ui]/[babel-runtime]/helpers/asyncToGenerator.js:35:14
  
  - new Promise
  
  - _export.js:36 new F
    [ui]/[core-js]/library/modules/_export.js:36:28

@kevincox
Copy link

Are there any plans to support es modules in the extract-loader?

@carsonreinke
Copy link
Author

@thequailman I was able to get it to work and created this example: https://github.com/carsonreinke/extract-loader-67

@kevincox yes, @cybercase was kind enough to put in a PR #69

carsonreinke added a commit to carsonreinke/reinke.co that referenced this issue Feb 24, 2020
@kamleshlikhare
Copy link

/// esModule: false, will solve your issue
{
loader: "file-loader",
options: {
name: "images/[name]-[hash:8].[ext]",
esModule: false
},

        }

@carsonreinke
Copy link
Author

@kamleshlikhare you don't need all the name stuff, just enabling option esModule.

Wondering if there is a way to enable that globally...

@scott-ln
Copy link

scott-ln commented Mar 3, 2020

The esModule: false solution isn't working for me, although I'm not very expert at package management and not sure if [email protected] is actually being used when I run my build, since older versions are present in the tree.

scott@laptop MINGW64 ~/project (master)
$ npm ls file-loader
[email protected] C:\Users\scott\project
+-- UNMET PEER DEPENDENCY @storybook/[email protected]
| `-- @storybook/[email protected]
|   `-- [email protected]
+-- [email protected]
| `-- [email protected]
+-- [email protected]
`-- [email protected]
  `-- [email protected]

npm ERR! peer dep missing: @storybook/react@^3, required by [email protected]

scott@laptop MINGW64 ~/project (master)
$ npm ls extract-loader
[email protected] C:\Users\scott\project
`-- [email protected]

@carsonreinke
Copy link
Author

@scott-ln well, you can't use 4.0.3, so you probably need to tweak those dependencies to get it up to >=5.0.2. Try setting file-loader dependency to =5.0.2 and see what happens.

@Luiz-Monad
Copy link

Luiz-Monad commented Mar 3, 2020

Isn't better doing what the val-loader does ?

import Module from 'module';
function exec(code, loaderContext) {
  const { resource, context } = loaderContext;

  const module = new Module(resource, parentModule);

  // eslint-disable-next-line no-underscore-dangle
  module.paths = Module._nodeModulePaths(context);
  module.filename = resource;

  // eslint-disable-next-line no-underscore-dangle
  module._compile(code, resource);

  return module.exports;
}

https://github.com/webpack-contrib/val-loader/blob/master/src/index.js#L10-L23

Or the Module would suffer from the same problem?

@Luiz-Monad
Copy link

Luiz-Monad commented Mar 3, 2020

Perhaps using ChildCompilation?

more...

After reading the WebPack to understand what happens after the File-Loader.
The file-loader is called by the Load-Runner from the NormalModule when the build happens.

After it the Acorn Parser runs and produces AST for the Harmony.
So we are at loss, there's no way to make webpack do that for us, because all export default is stripped in the AST level when WebPack convert the output to its Harmony dependencies.
The load-runner uses require and rely on loaders being CJS (even thou they output ES modules).
There's no way around except for creating a child compilation, or using babel. (as the Terser won't remove exports default clause, at least it appears to do so)

I think the cleanest way would be creating a child compilation targeting Node so WebPack can deal with it for us.
The easiest + also correct way would be babel, but incurs babel dependency.

sources:
https://github.com/webpack/loader-runner/blob/160c809d8d03cebe282fdb3b9d3cecedd4f6da5b/lib/loadLoader.js#L5
https://github.com/webpack/webpack/blob/503e6561d583f143896151a5b22e771f554773ec/lib/NormalModule.js#L793
https://github.com/webpack/webpack/blob/503e6561d583f143896151a5b22e771f554773ec/lib/javascript/JavascriptParser.js#L1602
https://github.com/webpack/webpack/blob/a488d073c3a0014ddafe5a56d34b57a7c934f94f/lib/dependencies/HarmonyExportDependencyParserPlugin.js#L125

@carsonreinke
Copy link
Author

@Luiz-Monad I think you might be reading into a bit much, the problem is simple, vm.Script does not support import syntax, just like the Node REPL. It is used here: https://github.com/peerigon/extract-loader/blob/master/src/extractLoader.js#L98

Will that Module work? MAYBE! I have not heard of it before, but it could be a better option then Babel.

@Luiz-Monad
Copy link

Luiz-Monad commented Mar 3, 2020

Actually I was over-complicating things.

I discovered this file.
https://github.com/jantimon/html-webpack-plugin/blob/master/lib/compiler.js

I just took this file and turned it into a loader, it does exactly what I needed.
I need it to process exactly like webpack would do it, and extract the resources (and preserve ES for tree-shaking reasions), that's why I was thinking in a Child Compilation, but it would be doing twice if I used this module and also child-compilation.
It does indeed solve the problem with modules by using Webpack itself.
And it actually does extract the resources because the require runs inside the loader-loaders ! and Webpack already taps require.

I just plugged it after my html-loader, works like a charm.

@simonppg
Copy link

simonppg commented Mar 4, 2020

After too many hours trying to work out why my Webpack config kept failing, I am very glad to have found this issue.

ERROR in ./src/test.html
Module build failed (from ./node_modules/extract-loader/lib/extractLoader.js):
D:\projects\src\images\london.jpg:1
export default __webpack_public_path__ + "dda88ae5192fe238f8384d1c0a2143db.jpg";
^^^^^^

SyntaxError: Unexpected token export
    at new Script (vm.js:79:7)
    at D:\projects\node_modules\extract-loader\lib\extractLoader.js:81:28
    at Generator.next (<anonymous>)
    at step (D:\projects\node_modules\babel-runtime\helpers\asyncToGenerator.js:17:30)
    at D:\projects\node_modules\babel-runtime\helpers\asyncToGenerator.js:35:14
    at new Promise (<anonymous>)
    at new F (D:\projects\node_modules\babel-runtime\node_modules\core-js\library\modules\_export.js:36:28)
    at D:\projects\node_modules\babel-runtime\helpers\asyncToGenerator.js:14:12
    at evalModule (D:\projects\node_modules\extract-loader\lib\extractLoader.js:150:63)
    at D:\projects\node_modules\extract-loader\lib\extractLoader.js:138:28
    at Generator.next (<anonymous>)
    at step (D:\projects\node_modules\babel-runtime\helpers\asyncToGenerator.js:17:30)
    at D:\projects\node_modules\babel-runtime\helpers\asyncToGenerator.js:28:13
    at process._tickCallback (internal/process/next_tick.js:68:7)
 @ ./src/js/app.js 8:0-23
error Command failed with exit code 2.

Rolling back to [email protected] fixed the problem for me

Rolling back works for me, thanks

@scott-ln
Copy link

scott-ln commented Mar 4, 2020

@carsonreinke wrote:

@scott-ln well, you can't use 4.0.3, so you probably need to tweak those dependencies to get it up to >=5.0.2. Try setting file-loader dependency to =5.0.2 and see what happens.

Sorry, I'm not sure what you mean? 4.0.3 is the latest version of extract-loader, not file-loader (which is installed at 5.0.2 in this scenario).

@carsonreinke
Copy link
Author

@scott-ln 🤦‍♂️ , sorry

@Luiz-Monad it sounds like this might be a better solution to using Babel, do you have anything you can share and we could possible get a PR together?

@jhnns
Copy link
Member

jhnns commented Mar 18, 2020

The issue should be solved with v5. Please re-open if that's not the case.

@jhnns jhnns closed this as completed Mar 18, 2020
@mnpenner
Copy link

@Luiz-Monad Can you elaborate a bit? It sounds like you're trying to do exactly what I'm trying to do.

I was trying to harvest some code from val-loader but even after I hacked around the "Unexpected token export" its choking on the next thing because webpack hasn't finished processing my file.

i.e., I want the evaluated/executed version of a file.

How did you convert compiler.js into a loader?

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

No branches or pull requests