Skip to content

Configuration setting to run babel on vendor files #342

@stof

Description

@stof
Member

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.

Activity

Lyrkan

Lyrkan commented on Jul 6, 2018

@Lyrkan
Collaborator

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

Encore.configureBabel(
    (options) => { /* NOOP */ },
    { exclude: /(node_modules|bower_components)/ }
);
andrewtch

andrewtch commented on Aug 27, 2018

@andrewtch

Very much needed feature. Is it scheduled for WP4?

weaverryan

weaverryan commented on Oct 8, 2018

@weaverryan
Member

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

vicdelfant commented on Oct 8, 2018

@vicdelfant

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

andrewtch commented on Oct 8, 2018

@andrewtch

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

Lyrkan commented on Oct 8, 2018

@Lyrkan
Collaborator

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

weaverryan commented on Oct 17, 2018

@weaverryan
Member

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

Lyrkan commented on Oct 17, 2018

@Lyrkan
Collaborator

@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

weaverryan commented on Oct 18, 2018

@weaverryan
Member

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

Lyrkan commented on Oct 18, 2018

@Lyrkan
Collaborator

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

I added the include_node_modules option to the PR.

added a commit that references this issue on Oct 26, 2018
b171eb4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @weaverryan@vicdelfant@stof@Lyrkan@andrewtch

      Issue actions

        Configuration setting to run babel on vendor files · Issue #342 · symfony/webpack-encore