diff --git a/src/content/guides/author-libraries.md b/src/content/guides/author-libraries.md
index bb131d7532c6..c0c8e159fcb5 100644
--- a/src/content/guides/author-libraries.md
+++ b/src/content/guides/author-libraries.md
@@ -6,14 +6,58 @@ contributors:
- johnstew
- simon04
- 5angel
+ - marioacc
---
-webpack is a tool which can be used to bundle application code and also to bundle library code. If you are the author of a JavaScript library and are looking to streamline your bundle strategy then this document will help you.
+Aside from applications, webpack can also be used to bundle JavaScript libraries. The following guide is meant for library authors looking to streamline their bundling strategy.
-## Author a Library
+## Authoring a Library
-Let's assume that you are writing a small library `webpack-numbers` allowing to convert numbers 1 to 5 from their numeric to a textual representation and vice-versa. The implementation makes use of ES2015 modules, and might look like this:
+Let's assume that you are writing a small library ,`webpack-numbers`, that allows users to convert the numbers 1 through 5 from their numeric representation to a textual one and vice-versa, e.g. 2 to 'two'.
+
+The basic project structure may look like this:
+
+__project__
+
+``` diff
++ |- webpack.config.js
++ |- package.json
++ |- /src
++ |- index.js
++ |- ref.json
+```
+
+Initialize npm, install webpack and lodash:
+
+``` bash
+npm init -y
+npm install --save-dev webpack lodash
+```
+
+__src/ref.json__
+
+```javascript
+[{
+ "num": 1,
+ "word": "One"
+}, {
+ "num": 2,
+ "word": "Two"
+}, {
+ "num": 3,
+ "word": "Three"
+}, {
+ "num": 4,
+ "word": "Four"
+}, {
+ "num": 5,
+ "word": "Five"
+}, {
+ "num": 0,
+ "word": "Zero"
+}]
+```
__src/index.js__
@@ -22,68 +66,79 @@ import _ from 'lodash';
import numRef from './ref.json';
export function numToWord(num) {
- return _.reduce(numRef, (accum, ref) => {
- return ref.num === num ? ref.word : accum;
- }, '');
+ return _.reduce(numRef, (accum, ref) => {
+ return ref.num === num ? ref.word : accum;
+ }, '');
};
export function wordToNum(word) {
- return _.reduce(numRef, (accum, ref) => {
- return ref.word === word && word.toLowerCase() ? ref.num : accum;
- }, -1);
+ return _.reduce(numRef, (accum, ref) => {
+ return ref.word === word && word.toLowerCase() ? ref.num : accum;
+ }, -1);
};
```
-The usage spec for the library will be as follows.
+The usage specification for the library use will be as follows:
```javascript
+// ES2015 module import
import * as webpackNumbers from 'webpack-numbers';
-
-...
-webpackNumbers.wordToNum('Two') // output is 2
-...
-
-// CommonJS modules
-
+// CommonJS module require
var webpackNumbers = require('webpack-numbers');
-
-...
-webpackNumbers.numToWord(3); // output is Three
-...
+// ...
+// ES2015 and CommonJS module use
+webpackNumbers.wordToNum('Two');
+// ...
+// AMD module require
+require(['webpackNumbers'], function ( webpackNumbers) {
+ // ...
+ // AMD module use
+ webpackNumbers.wordToNum('Two');
+ // ...
+});
```
-```html
-// Or as a script tag
+The consumer also can use the library by loading it via a script tag:
+``` html
...
```
-For full library configuration and code please refer to [webpack-library-example](https://github.com/kalcifer/webpack-library-example)
+Note that we can also configure it to expose the library in the following ways:
+
+- Property in the global object, for node.
+- Property in the `this` object.
+For full library configuration and code please refer to [webpack-library-example](https://github.com/kalcifer/webpack-library-example).
-## Configure webpack
-Now the agenda is to bundle this library
+## Base Configuration
-- Without bundling `lodash` but requiring it to be loaded by the consumer.
-- Name of the library is `webpack-numbers` and the variable is `webpackNumbers`.
-- Library can be imported as `import webpackNumbers from 'webpack-numbers'` or `require('webpack-numbers')`.
-- Library can be accessed through global variable `webpackNumbers` when included through `script` tag.
-- Library can be accessed inside Node.js.
+Now let's bundle this library in a way that will achieve the following goals:
+- Without bundling `lodash`, but requiring it to be loaded by the consumer using `externals`.
+- Setting the library name as `webpack-numbers`.
+- Exposing the library as a variable called `webpackNumbers`.
+- Being able to access the library inside Node.js.
-### Add webpack
+Also, the consumer should be able to access the library the following ways:
-Add basic webpack configuration.
+- ES2015 module. i.e. `import webpackNumbers from 'webpack-numbers'`.
+- CommonJS module. i.e. `require('webpack-numbers')`.
+- Global variable when included through `script` tag.
+
+We can start with this basic webpack configuration:
__webpack.config.js__
@@ -91,131 +146,160 @@ __webpack.config.js__
var path = require('path');
module.exports = {
- entry: './src/index.js',
- output: {
- path: path.resolve(__dirname, 'dist'),
- filename: 'webpack-numbers.js'
- }
+ entry: './src/index.js',
+ output: {
+ path: path.resolve(__dirname, 'dist'),
+ filename: 'webpack-numbers.js'
+ }
};
-
```
-This adds basic configuration to bundle the library.
-
-### Add `externals`
+## Externalize Lodash
-Now, if you run `webpack`, you will find that a largish bundle file is created. If you inspect the file, you will find that lodash has been bundled along with your code.
-It would be unnecessary for your library to bundle a library like `lodash`. Hence you would want to give up control of this external library to the consumer of your library.
+Now, if you run `webpack`, you will find that a largish bundle is created. If you inspect the file, you'll see that lodash has been bundled along with your code. In this case, we'd prefer to treat `lodash` as a `peerDependency`. Meaning that the consumer should already have `lodash` installed. Hence you would want to give up control of this external library to the consumer of your library.
-This can be done using the `externals` configuration as
+This can be done using the `externals` configuration:
__webpack.config.js__
-```javascript
-module.exports = {
- ...
- externals: {
- "lodash": {
- commonjs: "lodash",
- commonjs2: "lodash",
- amd: "lodash",
- root: "_"
- }
- }
- ...
-};
+``` diff
+ var path = require('path');
+
+ module.exports = {
+ entry: './src/index.js',
+ output: {
+ path: path.resolve(__dirname, 'dist'),
+ filename: 'webpack-numbers.js'
+- }
++ },
++ externals: {
++ lodash: {
++ commonjs: 'lodash',
++ commonjs2: 'lodash',
++ amd: 'lodash',
++ root: '_'
++ }
++ }
+ };
```
This means that your library expects a dependency named `lodash` to be available in the consumer's environment.
-If you only plan on using your library as a dependency in another webpack bundle, you may specify externals as an array.
+T> Note that if you only plan on using your library as a dependency in another webpack bundle, you may specify `externals` as an array.
-```javascript
-module.exports = {
- ...
- externals: [
- 'react',
- 'react-dom'
- ]
- ...
-};
-```
-Please note: for bundles that use several files from a package like this
+## External Limitations
-```javascript
-import A from 'library/A';
-import B from 'library/B';
-...
-```
+For libraries that use several files from a dependency:
-you wont be able to exclude them from bundle by specifying `library` in the externals.
+``` js
+import A from 'dependency/one';
+import B from 'dependency/two';
-You'll either need to exclude them one by one or by using a regular expression.
+// ...
+```
-```javascript
-module.exports = {
- ...
- externals: [
- 'library/A',
- 'library/B',
- /^library\/.+$/ // everything that starts with "library/"
- ]
- ...
-};
+You won't be able to exclude them from bundle by specifying `library` in the externals. You'll either need to exclude them one by one or by using a regular expression.
+
+``` js
+externals: [
+ 'library/one',
+ 'library/two',
+ // Everything that starts with "library/"
+ /^library\/.+$/
+]
```
-### Add `libraryTarget`
-For widespread use of the library, we would like it to be compatible in different environments, i. e. CommonJS, AMD, Node.js and as a global variable.
+## Expose the Library
-To make your library available for reuse, add `library` property in webpack configuration.
+For widespread use of the library, we would like it to be compatible in different environments, i.e. CommonJS, AMD, Node.js and as a global variable. To make your library available for consumption, add the `library` property inside `output`:
__webpack.config.js__
-```javascript
-module.exports = {
- ...
+``` diff
+ var path = require('path');
+
+ module.exports = {
+ entry: './src/index.js',
output: {
- ...
- library: 'webpackNumbers'
+ path: path.resolve(__dirname, 'dist'),
+- filename: 'webpack-numbers.js'
++ filename: 'webpack-numbers.js',
++ library: 'webpackNumbers'
+ },
+ externals: {
+ lodash: {
+ commonjs: 'lodash',
+ commonjs2: 'lodash',
+ amd: 'lodash',
+ root: '_'
+ }
}
- ...
-};
+ };
```
-This makes your library bundle to be available as a global variable when imported. To make the library compatible with other environments, add `libraryTarget` property to the config.
+This exposes your library bundle available as a global variable named `webpackNumbers` when imported. To make the library compatible with other environments, add `libraryTarget` property to the config. This will add the different options about how the library can be exposed.
__webpack.config.js__
-```javascript
-module.exports = {
- ...
+``` diff
+ var path = require('path');
+
+ module.exports = {
+ entry: './src/index.js',
output: {
- ...
- library: 'webpackNumbers',
- libraryTarget: 'umd'
+ path: path.resolve(__dirname, 'dist'),
+ filename: 'webpack-numbers.js',
+- library: 'webpackNumbers'
++ library: 'webpackNumbers',
++ libraryTarget: 'umd'
+ },
+ externals: {
+ lodash: {
+ commonjs: 'lodash',
+ commonjs2: 'lodash',
+ amd: 'lodash',
+ root: '_'
+ }
}
- ...
-};
+ };
```
+You can expose the library in the following ways:
+
+- Variable: as a global variable made available by a `script` tag (`libraryTarget:'var'`).
+- This: available through the `this` object (`libraryTarget:'this'`).
+- Window: available trough the `window` object, in the browser (`libraryTarget:'window'`).
+- UMD: available after AMD or CommonJS `require` (`libraryTarget:'umd'`).
+
If `library` is set and `libraryTarget` is not, `libraryTarget` defaults to `var` as specified in the [output configuration documentation](/configuration/output). See [`output.libraryTarget`](/configuration/output#output-librarytarget) there for a detailed list of all available options.
+W> With webpack 3.5.5, using `libraryTarget: { root:'_' }` doesn't work properly (as stated in [issue 4824](https://github.com/webpack/webpack/issues/4824)). However, you can set `libraryTarget: { var: '_' }` to expect the library as a global variable.
-### Final Steps
-[Tweak your production build using webpack](/guides/production).
+### Final Steps
-Add the path to your generated bundle as the package's main file in `package.json`
+Optimize your output for production by following the steps in the [production guide](/guides/production). Let's also add the path to your generated bundle as the package's `main` field in with our `package.json`
__package.json__
-```javascript
+``` json
+{
+ ...
+ "main": "dist/webpack-numbers.js",
+ ...
+}
+```
+
+Or, to add as standard module as per [this guide](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md#typical-usage):
+
+``` json
{
- "main": "dist/webpack-numbers.js",
- "module": "src/index.js", // To add as standard module as per https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md#typical-usage
+ ...
+ "module": "src/index.js",
+ ...
}
```