Skip to content

Commit 7950c8f

Browse files
authored
Merge pull request #269 from kalcifer/feat/how_to_shim
Adds docs for how to shim third party libraries Closes #13.
2 parents 750676e + d82e238 commit 7950c8f

File tree

1 file changed

+109
-6
lines changed

1 file changed

+109
-6
lines changed

content/how-to/shim.md

Lines changed: 109 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,111 @@
11
---
2-
title: How to Shim?
2+
title: How to Shim Third Party Libraries?
33
---
4-
> import-loader
5-
> exports-loader
6-
> expose-loader
7-
> ProvidePlugin
8-
> script-loader
4+
5+
`webpack` as a module bundler can understand modules written as ES2015 modules, CommonJS or AMD. But many times, while using third party libraries, we see that they expect dependencies which are global aka `$` for `jquery`. They might also be creating global variables which need to be exported. Here we will see different ways to help webpack understand these __broken modules__.
6+
7+
## Prefer unminified CommonJs/AMD files over bundled `dist` versions.
8+
9+
Most 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](/concepts/plugins#DedupePlugin)). However in most cases `dist` works fine as well.
10+
11+
``` javascript
12+
// webpack.config.js
13+
14+
module.exports = {
15+
...
16+
resolve: {
17+
alias: {
18+
jquery: "jquery/src/jquery"
19+
}
20+
}
21+
};
22+
```
23+
24+
## ProvidePlugin
25+
The [ProvidePlugin](/concepts/plugins#ProvidePlugin) makes a module available as a variable in every other module required by `webpack`. The module is required only if you use the variable.
26+
Most 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.
27+
28+
``` javascript
29+
var webpack = require("webpack");
30+
31+
...
32+
33+
plugins: [
34+
new webpack.ProvidePlugin({
35+
$: "jquery",
36+
jQuery: "jquery"
37+
})
38+
]
39+
```
40+
41+
## `imports-loader`
42+
43+
[`imports-loader`](https://github.com/webpack/imports-loader) inserts necessary globals into the required legacy module.
44+
For example, Some 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` using the `imports-loader`.
45+
46+
```javascript
47+
module: {
48+
loaders: [
49+
{
50+
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
51+
loader: "imports?this=>window"
52+
}
53+
]
54+
}
55+
```
56+
57+
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`
58+
59+
```javascript
60+
module: {
61+
loaders: [
62+
{
63+
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
64+
loader: "imports-loader?define=>false"
65+
}
66+
]
67+
}
68+
```
69+
70+
## `exports-loader`
71+
72+
Let's say a library creates a global variable that it expects it's consumers to use. In this case we can use [`exports-loader`](https://github.com/webpack/exports-loader), to export that global variable in CommonJS format.
73+
74+
```javascript
75+
module: {
76+
loaders: [
77+
{
78+
test: /[\/\\]node_modules[\/\\]some-module[\/\\]file\.js$/,
79+
loader: "exports-loader?file,parse=helpers.parse"
80+
// adds below code the the file's source:
81+
// exports["file"] = file;
82+
// exports["parse"] = helpers.parse;
83+
}
84+
]
85+
}
86+
```
87+
88+
## `scripts-loader`
89+
90+
The [scripts-loader](https://github.com/webpack/script-loader) evaluates code in the global context, just like you would add the code into a `script` tag. In this mode every normal library should work. require, module, etc. are undefined.
91+
Note: The file is added as string to the bundle. It is not minimized by `webpack`, so use a minimized version. There is also no dev tool support for libraries added by this loader.
92+
93+
```javascript
94+
require('script-loader!legacy.js')
95+
// This makes the global variable created by the legacy.js available to your application.
96+
// The above require will not return anything meaningful as a variable.
97+
98+
globalLegacyVariable() // This global variable will be added as a result of the script loader
99+
```
100+
101+
## `noParse` option
102+
103+
When 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.
104+
105+
```javascript
106+
module: {
107+
noParse: [
108+
/[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
109+
]
110+
}
111+
```

0 commit comments

Comments
 (0)