catamphetamine / universal-webpack

Isomorphic Webpack: both on client and server

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Absolute paths are marked as external

aight8 opened this issue · comments

When I use "import MyModule from 'app/my-module'" it's marked as external in the server build. When I use relative paths it's working.

Write it in the issue, don't write it here.
I'll answer there.

2016-07-08 12:42 GMT+03:00 Sebastian Fekete notifications@github.com:

When I use "import MyModule from 'app/my-module'" it's marked as external
in the server build. When I use relative paths it's working.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#10, or mute
the thread
https://github.com/notifications/unsubscribe/AAdH71J13S3JDsMwxQNCRnPHz-0bHl1Dks5qThuTgaJpZM4JH4Hh
.

Oh, I misunderstood your message, I thought it was an email (some people write me direct messages to my mailbox asking for assistance).

In your case the answer is simple:
https://github.com/halt-hammerzeit/universal-webpack/blob/master/source/server%20configuration.js#L47
universal-webpack adds all modules to externals array for server-side configuration.
It takes extra measures to exclude resolve stuff from there:
https://github.com/halt-hammerzeit/universal-webpack/blob/master/source/server%20configuration.js#L60
It should be working.

Ensure you're using the latest version:
npm install universal-webpack@latest --save

If it doesn't work with the latest version then you can upload a sample project for debugging.

        // Mark all node_modules as external
        if (/^[a-z\/\-0-9]+$/i.test(request))
        {
            return callback(null, request)
        }

Yeah I use the latest version and try to understand the whole code.
I don't get why this regex ensure that it's a nodes module.
I use in my code a lot absolute paths (for example: app/my-component/the-component). This will match the regex and it will be marked as external. Did I forget something? Otherwise this library is awesome and should be the future.

I use in my code a lot absolute paths (for example: app/my-component/the-component).

This is not an absolute filesystem path

This will match the regex and it will be marked as external.

Yes.
Is app your resolve.alias?

Did I forget something?

Maybe you're gonna need a new setting, something like not_external array of regexps.

I mean relative path but webpack specific root syntax ;)

root: path.resolve(__dirname, 'src'),

So when I require 'app/my-component' it tries to resolve first "....src/app/my-component.jsx" then it goes to the node_modules.

Why is it necessary to marking the files as external anyway? I understand what It does but not in this case. Isn't it the job of the developer to mark externals?

root: path.resolve(__dirname, 'src'),

Oh, I get it now.
Remove that setting and use resolve.alias instead:


const rootPath = path.resolve(__dirname, '../..')
const clientPath = path.resolve(rootPath, 'client')

const alias = {
  components: path.resolve(clientPath, 'components'),
  containers: path.resolve(clientPath, 'containers'),
  modules: path.resolve(clientPath, 'modules'),
  routes: path.resolve(clientPath, 'routes'),
  locales: path.resolve(clientPath, 'locales'),
  images: path.resolve(clientPath, 'assets/images'),
  styles: path.resolve(clientPath, 'assets/styles'),
  fonts: path.resolve(clientPath, 'assets/fonts'),
  utils: path.resolve(clientPath, 'utils'),
  src: clientPath
}

configuration = {
...

  resolve: {
    alias
  },
...
}

Why is it necessary to marking the files as external anyway?

So that webpack doesn't bundle all node_modules into the server-side build, because it's server side and no need to bundle them.

Okey than this issue is solved for now. But it's important information maybe for the doc later. I don't if this check is 100% clean because it's a dirty regex check and I don't know which other use cases exists out there. Let see :) Thanks for your help here 👍

But it's important information maybe for the doc later

Conversely, using root for resolving is not a common practice. resolve.alias is.

If you got it working with resolve.alias then you can close this issue.

For example there is the es6 variant of lodash (especially with webpack 2 treeshaking it's worth using it). It throws this error:

/xxx/frontend/node_modules/lodash-es/lodash.js:10
export { default as add } from './add.js';
^^^^^^

Because it's external. Hm.

It throws this error:

You haven't provided the stack trace of the error.

Because it's external.

Why do you think that's the reason

Externals are not transcompiled. And the export/import syntax is not availiable in native node. It's almost the only popular ES6 feature which is not featured by v8 js.

Externals are not transcompiled

Oh, I see it now.

Say, if I introduced a setting called exclude_from_externals which is an array of module names, would it be an appropriate solution?

I can imagine it could do it intelligently and scan all package.jsons in the node_modules folder for hints on ES6-only distribution.
Consider the aforementioned lodash:

https://npmcdn.com/lodash-es@4.13.1/package.json

"jsnext:main": "lodash.js",
"main": "lodash.js",

For example, the rule could be jsnext:main === main.

That would work for packages residing immediately in node_modules folder, but that wouldn't work for their dependencies, i guess (and dependencies of their dependencies).
And that would mess up different versions of same modules (say v 1.x uses ES5 and v 2.x uses ES6 and they both have the same name).

So, currently seems there's no bullet-proof solution to the ES6 modules issue.

If you come up with one you can write it here.

I'm currently implementing exclude_from_externals option.
Do you think you'll also need to add an include entry in babel-loader configuration for Babel to compile those ./node_modules/lodash-es/*.js files?

yes I had to extend the babel-loader:

      {
        test: /\.jsx?$/,
        loader: 'babel',
        include: [
          path.resolve(__dirname, 'src'),
          path.resolve(__dirname, 'node_modules', 'lodash-es'),
        ],
      },

But you have to add it anyway for client/server. So it's the job of the developer to make the loaders work properly. But the job from universal-webpack to don't break this settings.

I think your suggested solution with the exclude_from_externals field would be totally fine now. How do you check the entries? (startsWith/is in folder like in babel include/ etc. ?)

edit: isn't it possible to reuse this test from babel loader to check if it will compiled by babel? maybe the solution is there. that's a little bit more complex but maybe for the future.

Try the latest version, it should work

    exclude_from_externals:
    [
        'lodash-es'
    ]

Can be used, for example, for ES6-only node_modules. (a more intelligent solution would be accepted)
#10

Part of me wants to suggest that if my package.json "ecma" version field spec was noticed and implemented, then it would be easier for you to handle this automatically.

However. Realistically, I think the solution here for this case may be to recommend use of esm in auto mode.