Optionally disable dynamic requires

This 1-line file, when built with webpack, becomes 128K:

var moment = require('moment');

It seems that webpack is tripping up over the dynamic language requires and including all 60+ languages that come with moment. I’d love a mechanism of turning off this feature that can sometimes be too smart for its own good.

@jmorrel @petehunt this was the culprit behind the huge file sizes.

relevant: #59

@sokra would you accept a patch enabling something like resolve.dynamic: false?

Author: Fantashit

9 thoughts on “Optionally disable dynamic requires

  1. webpack just includes what the module requires. moment requires all its languages so they are included in the bundle. Just because browserify doesn’t “find” that dependencies, we don’t have to adopt this (wrong) behavior. The defaults are choosen to get the best support for modules. If we don’t include the languages moment won’t work or you would need to manually include the languages.

    You can change the default with the ContentReplacementPlugin for a specified directory. This is only a one line addition and you need to choose the languages anyway.

    browserify:

    • just require("moment") won’t work, because no languages are loaded.
    • choose the languages by require("moment") plus require("moment/lang/en")

    webpack:

    • just require("moment") will work. all languages are included.
    • choose the languages with the ContextReplacementPlugin and do require("moment")
  2. Random ProTip™ for anyone just stumbling into this, with moment 2.0 the folder is called locale and not lang. So the IgnorePlugin line is

     new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    
  3. I’m using the noParse options.

    module: {
      noParse: [/moment.js/]
    }
    

    according to the doc http://webpack.github.io/docs/configuration.html#module-noparse

    The files are expected to have no call to require, define or similar. They are allowed to use exports and module.exports. Which means that the file is not parsed using the regex that includes everything, but it still gets exported. It’s pretty much the perfect behavior.

    One should use this option for a browser build and require elsewhere the locale data they want, or remove the noParse server side.

  4. @sokra disabling expression require doesn’t seem to work for me

    {
      module: {
        // require
        unknownContextRegExp: /$^/,
        unknownContextCritical: false,
    
        // require(expr)
        exprContextRegExp: /$^/,
        exprContextCritical: false,
    
        // require("prefix" + expr + "surfix")
        wrappedContextRegExp: /$^/,
        wrappedContextCritical: false
      }
    }
    

    I tried this but nothing changed, webpack keeps trying to handle it

    my code looks like:

    var scriptPath = path.join(process.cwd(), "datafiles", "scripts", "public", req.params[0]);
    
    var Script = require(scriptPath);
    

    this code is executed with every request and requires a particular file, but as webpack is trying to wrap it the module is not found

    the code after webpack is

    var scriptPath = _path2.default.join(process.cwd(), "datafiles", "scripts", "public", req.params[0]);
    
    var Script = __webpack_require__(34)(scriptPath);
    

    I should point out that I’m using webpack to bundle my server files and then bundling it with Electron.

  5. thanks @Sinewyk !

    webpack:

    module:  {
      ...
      noParse: [/moment.js/]
    }
    

    your code

    import moment from "moment"
    import "moment/locale/fr"
    moment.locale("fr")
    
    or 
    
    const moment = require("moment")
    require("moment/locale/fr")
    moment.locale("fr")
    

    it’s nice

  6. How about ignoring all locales with IgnorePlugin except some of my choosing? For example, ignore all except EN, ES, FR. Can that be done with a regular expression?

    plugins: [
      new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
    ]

    Edit: I figured It out, in case someone still needs it. Found in https://stackoverflow.com/a/25426019/2477303

    plugins: [
      new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en|es|fr/),
      // new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
    ]

Comments are closed.