Skip to content

Commit d46e8f6

Browse files
iclantonVesaJuvonen
authored andcommitted
Updating the "Extending Webpack" documentation. (SharePoint#929)
1 parent d95e710 commit d46e8f6

File tree

1 file changed

+73
-42
lines changed

1 file changed

+73
-42
lines changed
Lines changed: 73 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,134 @@
11
---
2-
title: Extending webpack in the SharePoint Framework toolchain
2+
title: Extending Webpack in the SharePoint Framework toolchain
33
ms.date: 09/25/2017
44
ms.prod: sharepoint
55
---
66

77

8-
# Extending webpack in the SharePoint Framework toolchain
8+
# Extending Webpack in the SharePoint Framework toolchain
99

10-
[Webpack](https://webpack.github.io/) is a JavaScript module bundler that takes your JavaScript files and its dependencies and generates one or more JavaScript bundles so you can load different bundles for different scenarios.
10+
[Webpack](https://Webpack.js.org/) is a JavaScript module bundler that takes your JavaScript files and their dependencies and generates one or more JavaScript files so you can load different pieces of code for different scenarios.
1111

12-
The framework tool chain uses CommonJS for bundling. This enables you to define modules and where you want to use them. The tool chain also uses SystemJS, a universal module loader, to load your modules. This helps you to scope your web parts by making sure that each web part is executed in its own namespace.
12+
The framework toolchain uses CommonJS for bundling. This enables you to define modules and where you want to use them. The toolchain also uses SystemJS, a universal module loader, to load your modules. This helps you to scope your web parts by making sure that each web part is executed in its own namespace.
1313

14-
One common task you would want to add to the SharePoint Framework toolchain is to extend the webpack configuration with custom loaders and plugins.
14+
One common task you would want to add to the SharePoint Framework toolchain is to extend the Webpack configuration with custom loaders and plugins.
1515

16-
## Using webpack loaders
17-
There are many cases where one would like to import and utilize a non-JavaScript resource during development, typically this is done with images or templates. A [webpack loader](https://webpack.github.io/docs/loaders.html) will convert the resource into something that can be utilized by your JavaScript application. For example, a Markdown template may be compiled and converted to a text string, while a image resource may be converted to Base64 image.
16+
## Using Webpack loaders
17+
There are many cases where one would like to import and utilize a non-JavaScript resource during development, typically this is done with images or templates. A [Webpack loader](https://webpack.js.org/loaders/) will convert the resource into something that can be utilized by your JavaScript application or provide a simple reference that your JavaScript application can understand. For example, a Markdown template may be compiled and converted to a text string, while a image resource may be converted to an inlined Base64 image, or it may be referenced as a URL and copied to your `dist` directory for deployment.
1818

19-
There are a number of useful loaders, several of which are already used by the standard SharePoint Framework webpack configuration, such as:
19+
There are a number of useful loaders, several of which are already used by the standard SharePoint Framework Webpack configuration, such as:
2020

2121
- html-loader
2222
- json-loader
2323
- loader-load-themed-styles
2424

25-
Extending the framework webpack configuration with custom loaders is a straightforward process which is documented [here in the webpack documentation](https://webpack.github.io/docs/loaders.html#writing-a-loader).
25+
Extending the framework Webpack configuration with custom loaders is a straightforward process which is documented [here in the Webpack documentation](https://webpack.js.org/contribute/writing-a-loader/).
2626

27-
> You can find more details on the loaders from [webpack loaders documentation](https://webpack.github.io/docs/loaders.html)
27+
> You can find more details on the loaders from [Webpack loaders documentation](https://webpack.js.org/loaders/)
2828
2929
## Example: Using the markdown-loader package
30-
As an example, let's use the [markdown-loader package](https://www.npmjs.com/package/markdown-loader). It's a loader which allows you to reference an `.md` file and output it as HTML string.
30+
As an example, let's use the [markdown-loader package](https://www.npmjs.com/package/markdown-loader). It's a loader which allows you to reference an `.md` file and output it as an HTML string.
3131

32-
You can download the completed sample [here](https://aka.ms/spfx-extend-webpack-sample).
32+
You can download the completed sample [here](https://aka.ms/spfx-extend-Webpack-sample).
3333

3434
### Step 1 - Install the package
3535
Let's reference markdown-loader in our project.
3636

3737
```
38-
npm i --save markdown-loader
38+
npm i --save markdown-loader
3939
```
4040

41-
### Step 2 - Configure Webpack
42-
Now that we have the package installed, lets now configure the SharePoint Framework webpack configuration to include the markdown-loader.
41+
### Step 2 - Configure Webpack
42+
Now that we have the package installed, lets now configure the SharePoint Framework Webpack configuration to include `markdown-loader`.
4343

44-
In the [documentation of markdown-loader](https://github.com/peerigon/markdown-loader), it shows how to extend the webpack configuration to include the loader:
44+
In the [documentation of markdown-loader](https://github.com/peerigon/markdown-loader), it shows how to extend the Webpack configuration to include the loader:
4545

4646
```JavaScript
4747
{
4848
module: {
49-
loaders: [
50-
{ test: /\.md$/, loader: "html!markdown" }
49+
rules: [
50+
{
51+
test: /\.md$/,
52+
use: [
53+
{
54+
loader: 'html-loader'
55+
},
56+
{
57+
loader: 'markdown-loader',
58+
options: {
59+
/* options for markdown-loader here */
60+
}
61+
}
62+
]
63+
}
5164
]
5265
}
5366
}
5467
```
5568

56-
We will use this information to configure it in our project.
69+
Let's take a look at what this configuration is doing:
70+
- The `rules` array in the Webpack configuration defines a set of file path tests and the loaders that should be used when a resource is found that matches the test. In this case, the `test` property checks for file paths that end with `.md`.
71+
- The `use` array describes a list of loaders that are applied sequentially to the resource. They are applied from last to first. In this case, the first loader to be applied will be `markdown-loader` and the last loader to be applied will be `html-loader`.
72+
- When multiple loaders are specified, the result of each loader is piped to the next.
5773

58-
In order to add this custom loader into the SharePoint Framework webpack configuration, we will need to instruct the build task to configure webpack. The build tasks are defined in the gulp file - `gulpfile.js` - which is located at the root of your project. SharePoint Framework uses [gulp](http://gulpjs.com/) as its task runner and hence we use it to define and register custom tasks with the gulp task runner.
74+
We will use this information to configure it in our project.
5975

60-
Edit the `gulpfile.js` and add the following code right before `build.initialize(gulp);`:
76+
In order to add this custom loader into the SharePoint Framework Webpack configuration, we will need to instruct the build task to configure Webpack. The build tasks are defined in the gulp file - `gulpfile.js` - which is located at the root of your project.
6177

62-
```JavaScript
63-
build.configureWebpack.mergeConfig({
64-
additionalConfiguration: (generatedConfiguration) => {
65-
generatedConfiguration.module.loaders.push([
66-
{ test: /\.md$/, loader: "html!markdown" }
67-
]);
78+
Edit the `gulpfile.js` and add the following code right before `build.initialize(gulp);`:
6879

69-
return generatedConfiguration;
70-
}
80+
```JavaScript
81+
build.configureWebpack.mergeConfig({
82+
additionalConfiguration: (generatedConfiguration) => {
83+
generatedConfiguration.module.rules.push(
84+
{
85+
test: /\.md$/,
86+
use: [
87+
{
88+
loader: 'html-loader'
89+
},
90+
{
91+
loader: 'markdown-loader'
92+
}
93+
]
94+
}
95+
);
96+
97+
return generatedConfiguration;
98+
}
7199
});
72100
```
73101

74-
Notice that we simply push the loader config onto the list of existing loaders in the toolchain. It's important to ensure that your `additionalConfiguration` function ends with the `return generatedConfiguration` line, as this ensures that it returns the loader configuration to the toolchain.
102+
Let's walk through what this code snippet is doing:
103+
- As its name implies, the `ConfigureWebpackTask` (instantiated as `build.configureWebpack`) configures webpack for us. There is a lot of special configuration that happens to build SPFx projects, so there is some nontrivial logic in this task.
104+
- The `ConfigureWebpackTask` takes an optional `additionalConfiguration` property. We want to set this property to a function which takes the generated configuration, makes our modifications to it, and then returns the updated configuration. **Note that this function must return a Webpack configuration to the toolchain, otherwise Webpack will not be configured correctly.**
105+
- Inside the body of the function that we set to `additionalConfiguration`, simply push a new rule onto the existing set of rules in the configuration. Notice that this new rule is very similar to example in the configuration snippet at the top of **Step 2**.
75106

76-
> While you are able to completely replace the toolchain's default webpack configuration using this approach, to get the maximum benefit with performance and optimization, it is not recommended to do so unless stated otherwise in the documentation.
107+
> While you are able to completely replace the toolchain's default Webpack configuration using this approach, to get the maximum benefit with performance and optimization, it is not recommended to do so unless stated otherwise in the documentation.
77108
78109
### Step 3 - Update your code
79-
Now that we have configured the loader, lets update our code and add few files to test the scenario.
110+
Now that we have configured the loader, lets update our code and add few files to test the scenario.
80111

81112
Create a file `my-markdown.md` in the `src` directory of your project folder with some Markdown text in it.
82113

83114
```md
84115
#Hello Markdown
85116

86-
*Markdown* is a simple markup format to write content.
117+
*Markdown* is a simple markup format to write content.
87118

88-
You can also format text as **bold** or *italics* or ***bold italics***
119+
You can also format text as **bold** or *italics* or ***bold italics***
89120
```
90121

91-
When you build the project, the webpack markdown-loader will convert this markdown text to a HTML string. To use this HTML string in any of your source `*.ts` files, add the following `require()` line at the top of the file after your imports, for example:
122+
When you build the project, the Webpack markdown-loader will convert this markdown text to a HTML string. To use this HTML string in any of your source `*.ts` files, add the following `require()` line at the top of the file after your imports, for example:
92123

93124

94125
```TypeScript
95-
const strMarkdownString = require("../../../../src/readme.md") as string;
126+
const markdownString: string = require<string>('./../../../../src/readme.md');
96127
```
97128

98-
Webpack by default will look in the `lib` folder for the file, but by default `.md` files don't get copied to the `lib` folder, meaning we need to create a rather lengthy relative path. We can control this setting by defining a config file to tell the toolchain to copy `md` files to the lib folder.
129+
Webpack by default will look in the `lib` folder for the file, but by default `.md` files don't get copied to the `lib` folder, meaning we need to create a rather lengthy relative path. We can control this setting by defining a config file to tell the toolchain to copy `md` files to the lib folder.
99130

100-
Create a file `copy-static-assets.json` in the `config` directory to tell the build system to copy some additional files from `src` to `lib`. By default, this build task copies files with extensions that the default toolchain webpack configuration understands (like `png` and `json`), so we just need to tell it to also copy `md` files.
131+
Create a file `copy-static-assets.json` in the `config` directory to tell the build system to copy some additional files from `src` to `lib`. By default, this build task copies files with extensions that the default toolchain Webpack configuration understands (like `png` and `json`), so we just need to tell it to also copy `md` files.
101132

102133
```JSON
103134
{
@@ -110,14 +141,14 @@ Create a file `copy-static-assets.json` in the `config` directory to tell the bu
110141
Now instead of using the relative path, you can use the file path in your `require` statement, for example:
111142

112143
```TypeScript
113-
const strMarkdownString = require("../../readme.md") as string;
144+
const markdownString: string = require<string>('./../../readme.md');
114145
```
115-
146+
116147
You can then reference this string in your code, for example:
117148

118149
``` TypeScript
119150
public render(): void {
120-
this.domElement.innerHTML = strMarkdownString;
151+
this.domElement.innerHTML = markdownString;
121152
}
122153
```
123154

@@ -126,4 +157,4 @@ To build and test your code, execute the following command in a console in the r
126157

127158
```
128159
gulp serve
129-
```
160+
```

0 commit comments

Comments
 (0)