Need to have doc created.
You've mixed different approaches how to include legacy vendor modules. This is how I'd tackle it:
distMost modules link the dist version in the main field of their package.json. While this is useful for most developers, for webpack it is better to alias the src version because this way webpack is able to optimize dependencies better (e.g. when using the DedupePlugin).
// webpack.config.js
module.exports = {
...
resolve: {
alias: {
jquery: "jquery/src/jquery"
}
}
};
However, in most cases the dist version works just fine as well.
ProvidePlugin to inject implicit globalsMost legacy modules rely on the presence of specific globals, like jQuery plugins do on $ or jQuery. In this scenario you can configure webpack, to prepend var $ = require("jquery") everytime it encounters the global $ identifier.
var webpack = require("webpack");
...
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
thisSome legacy modules rely on this being the window object. This becomes a problem when the module is executed in a CommonJS context where this equals module.exports. In this case you can override this with the imports-loader.
Run npm i imports-loader --save-dev and then
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports?this=>window"
}
]
}
The imports-loader can also be used to manually inject variables of all kinds. But most of the time the ProvidePlugin is more useful when it comes to implicit globals.
There are modules that support different module styles, like AMD, CommonJS and legacy. However, most of the time they first check for define and then use some quirky code to export properties. In these cases, it could help to force the CommonJS path by setting define = false.
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports?define=>false"
}
]
}
If you don't care about global variables and just want legacy scripts to work, you can also use the script-loader. It executes the module in a global context, just as if you had included them via the <script> tag.
noParse to include large distsWhen there is no AMD/CommonJS version of the module and you want to include the dist, you can flag this module as noParse. Then webpack will just include the module without parsing it, which can be used to improve the build time. This means that any feature requiring the AST, like the ProvidePlugin, will not work.
module: {
noParse: [
/[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
]
}
Note that this topic has huge overlaps with #13, maybe merge them?
Yeah. Closing this in favor of #13. I added a mention there that we won't forget that comment.
Most helpful comment
You've mixed different approaches how to include legacy vendor modules. This is how I'd tackle it:
1. Prefer unminified CommonJS/AMD over
distMost modules link the
distversion in themainfield of theirpackage.json. While this is useful for most developers, for webpack it is better to alias thesrcversion because this way webpack is able to optimize dependencies better (e.g. when using theDedupePlugin).However, in most cases the
distversion works just fine as well.2. Use the
ProvidePluginto inject implicit globalsMost legacy modules rely on the presence of specific globals, like jQuery plugins do on
$orjQuery. In this scenario you can configure webpack, to prependvar $ = require("jquery")everytime it encounters the global$identifier.3. Use the imports-loader to configure
thisSome legacy modules rely on
thisbeing thewindowobject. This becomes a problem when the module is executed in a CommonJS context wherethisequalsmodule.exports. In this case you can overridethiswith the imports-loader.Run
npm i imports-loader --save-devand thenThe imports-loader can also be used to manually inject variables of all kinds. But most of the time the
ProvidePluginis more useful when it comes to implicit globals.4. Use the imports-loader to disable AMD
There are modules that support different module styles, like AMD, CommonJS and legacy. However, most of the time they first check for
defineand then use some quirky code to export properties. In these cases, it could help to force the CommonJS path by settingdefine = false.5. Use the script-loader to globally import scripts
If you don't care about global variables and just want legacy scripts to work, you can also use the script-loader. It executes the module in a global context, just as if you had included them via the
<script>tag.6. Use
noParseto include large distsWhen there is no AMD/CommonJS version of the module and you want to include the
dist, you can flag this module asnoParse. Then webpack will just include the module without parsing it, which can be used to improve the build time. This means that any feature requiring the AST, like theProvidePlugin, will not work.