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

Configuration setting to run babel on vendor files #342

Closed
stof opened this issue Jul 3, 2018 · 10 comments · Fixed by #401
Closed

Configuration setting to run babel on vendor files #342

stof opened this issue Jul 3, 2018 · 10 comments · Fixed by #401
Labels

Comments

@stof
Copy link
Member

@stof stof commented Jul 3, 2018

Currently, Encore forces to exclude node_modules and bower_components from the babel-loader. However, publishing ES2016 code is becoming more common, so this causes issues for some users (see #341 for the latest report related to this, but there are many others in the issue tracker).

I think we should make this behavior configurable.

@Lyrkan

This comment has been minimized.

Copy link
Collaborator

@Lyrkan Lyrkan commented Jul 6, 2018

I agree, maybe we should add it to the configureBabel() method?

Encore.configureBabel(
    (options) => { /* NOOP */ },
    { exclude: /(node_modules|bower_components)/ }
);
@Lyrkan Lyrkan added the feature label Jul 6, 2018
@andrewtch

This comment has been minimized.

Copy link

@andrewtch andrewtch commented Aug 27, 2018

Very much needed feature. Is it scheduled for WP4?

@weaverryan

This comment has been minimized.

Copy link
Member

@weaverryan weaverryan commented Oct 8, 2018

This now has a PR! Question: what will be the most common way to use this new option? Will people entirely want to stop excluding node_modules? Or will they want to exclude most of node_modules but “whitelist” just a few modules that need to go through ES6? I haven’t benchmarked it, but I believe including ALL of node_modules is a huge performance hit. I’m asking to make sure the PR gives users what they need easily.

@vicdelfant

This comment has been minimized.

Copy link

@vicdelfant vicdelfant commented Oct 8, 2018

IMHO, it would be great if we could whitelist just a few modules. We've used Webpack in quite a few projects and the cases where we had/preferred to use the ES6 sources are very limited (though increasing). I doubt that including everything in the node_modules folder is worth the performance hit.

Switching to a "whitelist all by default" strategy later on can be done without breaking backwards-compatibility while the other way around (first including everything and then using a whitelist-only option) would break compatibility.

@andrewtch

This comment has been minimized.

Copy link

@andrewtch andrewtch commented Oct 8, 2018

I've recently dropped encore for all active projects and switched to WP4 with full babel. Actually, it takes around 40s to start and 2-3 seconds to recompile. Disabling babel results in 30s to start and 2-3 seconds to recompile, so it does not make any difference.

On every project recompiling everything with babel was a critical point, because there are a lot of people with chrome 32 and firefox 28 ) and, unfortunately, they do convert.

@Lyrkan

This comment has been minimized.

Copy link
Collaborator

@Lyrkan Lyrkan commented Oct 8, 2018

Whitelisting can be done within the exclude option, either by using a regexp with negative lookahead (which is fine if you don't have a lot of things to whitelist, but can get a bit messy) or by giving it a function.

Another solution could be to add new method that takes a list of paths to whitelist and create new rules accordingly (some sort of pre-configured Encore.addLoader(...)).

@weaverryan

This comment has been minimized.

Copy link
Member

@weaverryan weaverryan commented Oct 17, 2018

Hmm. Based on feedback, I think it should be simple to:

A) load everything through Babel
and
B) whitelist just specific modules

With the PR, (A) is for sure easy. @Lyrkan with a callback, is (B) also pretty easy? If so, we would just need some docs above the method on the PR - then I think we'd be good to go.

@Lyrkan

This comment has been minimized.

Copy link
Collaborator

@Lyrkan Lyrkan commented Oct 17, 2018

@weaverryan That depends on what you mean by pretty easy. I think the following callback would work fine:

const path = require('path');

Encore.configureBabel(() => {}, {
  exclude: (filePath) => {
    // Don't exclude files outside of node_modules
    if (!/node_modules/.test(filePath)) {
      return false;
    }

    // Don't exclude whitelisted modules
    const whitelistedModules = ['foo', 'bar', 'baz'].map(
       module => path.join('node_modules', module) + path.sep
    );

    for (const modulePath of whitelistedModules) {
      if (filePath.includes(modulePath)) {
        return false;
      }
    }
  
    // Exclude other files
    return true;
  }
});

But most of the complexity comes from two things:

  • the path separator that's not the same based on the build platform (which requires using path.join(...))
  • handling things like including a module called "foo" but not another one called "foobar" (hence the path.sep concatenation)

There are other ways than using a function to do it but I'm not sure that they are easier to understand, for instance:

// Using a negative lookahead RegExp without
// platform-specific separator
Encore.configureBabel(() => {}, {
  exclude: /node_modules(?!\/(foo|bar|baz))/
});

// Using a negative lookahead RegExp with
// platform-specific separator
Encore.configureBabel(() => {}, {
  exclude: /node_modules(?!(\/|\\)(foo|bar|baz))/
});

// Using a negative lookahead RegExp with
// platform-specific separator and trailing
// separator
Encore.configureBabel(() => {}, {
  exclude: /node_modules(?!(\/|\\)(foo|bar|baz)(\/|\\))/
});

// Using another Condition object without
// platform-specific separator
Encore.configureBabel(() => {}, {
  exclude: {
    test: /node_modules/,
    exclude: [
      /node_modules\/foo/,
      /node_modules\/bar/,
      /node_modules\/baz/,
    ]
  }
});

// Using another Condition object with
// platform-specific separator
Encore.configureBabel(() => {}, {
  exclude: {
    test: /node_modules/,
    exclude: [
      /node_modules(\/|\\)foo/,
      /node_modules(\/|\\)bar/,
      /node_modules(\/|\\)baz/,
    ]
  }
});

// Using another Condition object with
// platform-specific separator and trailing
// separator
Encore.configureBabel(() => {}, {
  exclude: {
    test: /node_modules/,
    exclude: [
      /node_modules(\/|\\)foo(\/|\\)/,
      /node_modules(\/|\\)bar(\/|\\)/,
      /node_modules(\/|\\)baz(\/|\\)/,
    ]
  }
});
@weaverryan

This comment has been minimized.

Copy link
Member

@weaverryan weaverryan commented Oct 18, 2018

Hahahaha. Wow. I'm super impressed that you were able to compile all these solutions... because they are HARD! Or, at least, not obvious :D. Yes, I don't love them - as you were probably going to guess.

My next proposal/idea:

  1. Keep the exclude key you added (after all, this is the correct/official way to handle this)
  2. Add a new include_node_modules key that's a simple array of node "modules" that should be included. We would generate the exclude key needed for them automatically. Obviously, these options cannot be combined.

WDYT?

@Lyrkan

This comment has been minimized.

Copy link
Collaborator

@Lyrkan Lyrkan commented Oct 18, 2018

@weaverryan Yeah, I kinda knew you weren't gonna like it :)

I added the include_node_modules option to the PR.

weaverryan added a commit that referenced this issue Oct 26, 2018
…eBabel (Lyrkan)

This PR was squashed before being merged into the master branch (closes #401).

Discussion
----------

Allow to configure the JS exclude rules through configureBabel

This PR closes #342 by allowing to configure the js/jsx loaders' exclude rule by using `configureBabel()`.

For instance:

```js
Encore.configureBabel(
    () => {},
    { exclude: /foo/ }
);
```

Note that it doesn't change the default behavior that excludes `node_modules` and `bower_components`.

**Edit:**

Also adds an `include_node_modules` option to use the default `exclude` rule but only include some Node modules (can't be used if the `exclude` option is also set):

```js
Encore.configureBabel(
    () => {},
    { include_node_modules: ['foo', 'bar', 'baz'] }
);
```

Commits
-------

a07238c Add an example of calling configureBabel with the "include_node_modules" option
714a732 Add "include_node_modules" option to configureBabel
6c8f073 Allow to configure the JS exclude rules through configureBabel
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.