Using webpack for Custom Builds
webpack is a module bundler for JavaScript. It can basically process the code in your application and bundle it up, not only into a single file, but bundled files that can be dynamically loaded as needed at runtime, for example, in an application that might have multiple routes. You can use webpack to build applications that use the ArcGIS API for JavaScript by using the @arcgis/webpack-plugin.
To learn more about webpack, please refer to the concepts and guides pages from webpack.
Prerequisites
- Node.js version
8.x.x
or higher (includes npm, the node package manager)
To check if these are installed:
node --version
Getting Started
We provide a sample application hosted on Github under the webpack directory in the jsapi-resources repository for you to get started.
jsapi-resources/4.x/webpack/demo
├── README.md
├── package-lock.json
├── package.json
├── src
│ ├── assets
│ │ ├── favicon.ico
│ │ ├── green-blue-small.png
│ │ └── icons
│ │ └── icon.png
│ ├── components
│ │ ├── header.tsx
│ │ └── webmapview.tsx
│ ├── config.ts
│ ├── css
│ │ ├── index.scss
│ │ └── main.scss
│ ├── index.html
│ └── index.tsx
├── tsconfig.json
└── webpack.config.js
However, if you prefer to start from scratch you can install the @arcgis/webpack-plugin yourself.
npm install --save-dev @arcgis/webpack-plugin@^4.8.2
You can also clone the jsapi-resources repository (code below) to your local machine or download the repository to your local machine.
git clone https://github.com/Esri/jsapi-resources.git
Understanding webpack
In the provided webpack sample, you are given some npm scripts in the package.json
as shortcuts for your development environment.
Note: If you are new to node and are unfamiliar or need a refresher on what is contained in a package.json file, please refer to the documentation.
package.json
- scriptspackage.json
- dependenciespackage.json
- devDependenciespackage.json
- npm-scripts
Your package.json
will look something like this.
{
"name": "arcgis-webpack-plugin-sample",
...
"dependencies": {
"@arcgis/webpack-plugin": "^4.8.2"
}
}
What this file is saying is that when you do npm install
it will install the latest version of the @arcgis/webpack-plugin
, which has a dependency on version 4.9 of the ArcGIS API for JavaScript that it will also install locally. This tells node to download any dependencies
and/or devDependencies
listed in the package.json
file.
The scripts
field in the package.json
file is used to issue commands to build your application. The webpack-dev-server is a useful development server that also provides live reloading of your application as you write your code.
{
...
"scripts": {
"start": "webpack-dev-server --mode development --open",
"build": "webpack --mode production"
}
...
}
See the package.json file in the webpack sample for more information.
Building your app
For both options (clone or download), you need to copy the source files from https://github.com/Esri/jsapi-resources/tree/master/4.x/webpack/demo
to a new directory. In the following steps, we'll name the new directory esrijs-webpack
.
The contents of your directory should appear as follows:
esrijs-webpack
├── README.md
├── package-lock.json
├── package.json
├── src
│ ├── assets
│ │ ├── favicon.ico
│ │ ├── green-blue-small.png
│ │ └── icons
│ │ └── icon.png
│ ├── components
│ │ ├── header.tsx
│ │ └── webmapview.tsx
│ ├── config.ts
│ ├── css
│ │ ├── index.scss
│ │ └── main.scss
│ ├── index.html
│ └── index.tsx
├── tsconfig.json
└── webpack.config.js
- Open a terminal window or shell command window
- Change directory to
esrijs-webpack
- In the terminal window run:
npm install
- The first time this is run it may take a while
- In the terminal window run:
- In the terminal window type
npm start
and press return - The command will run the webpack bundler using the
@arcgis/webpack-plugin
- Your application will be available at
http://localhost:8080/
- You can build a deployable version of your app by running
npm run build
. - This will take a little longer and build a deployable version of your application in a
dist
folder.
The critical portion of creating your application is going to be your webpack.config.js
.
Note: To learn more about webpack, please refer to the concepts and guides pages from webpack.
See the configuration section of the webpack documentation for details on each of the options available in the configuration file.
const ArcGISPlugin = require("@arcgis/webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const path = require("path");
const webpack = require("webpack");
module.exports = {
entry: {
index: "./src/index.tsx"
},
output: {
filename: "[name].bundle.js",
publicPath: ""
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: "ts-loader",
options: {
transpileOnly: true
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: false }
}
],
exclude: /node_modules/
},
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
}
]
},
plugins: [
// Be sure to have the @arcgis/webpack-plugin run first in the list
new CleanWebpackPlugin(["dist"]),
new ArcGISPlugin(),
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html",
chunksSortMode: "none"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
],
resolve: {
modules: [path.resolve(__dirname, "/src"), "node_modules/"],
extensions: [".ts", ".tsx", ".js", ".scss"]
},
externals: [
(context, request, callback) => {
if (/pe-wasm$/.test(request)) {
return callback(null, "amd " + request);
}
callback();
}
],
node: {
process: false,
global: false
}
};
In the current version of the @arcgis/webpack-plugin
, you need to configure the application to use the workers of the ArcGIS API for JavaScript from the cdn. The workers configuration for this sample application is located under jsapi-resources/4.x/webpack/demo/src/config.ts
.
import esriConfig = require("esri/config");
const DEFAULT_WORKER_URL = "https://js.arcgis.com/4.9/";
const DEFAULT_LOADER_URL = `${DEFAULT_WORKER_URL}dojo/dojo-lite.js`;
(esriConfig.workers as any).loaderUrl = DEFAULT_LOADER_URL;
esriConfig.workers.loaderConfig = {
baseUrl: `${DEFAULT_WORKER_URL}dojo`,
packages: [
{ name: "esri", location: DEFAULT_WORKER_URL + "esri" },
{ name: "dojo", location: DEFAULT_WORKER_URL + "dojo" },
{ name: "dojox", location: DEFAULT_WORKER_URL + "dojox" },
{ name: "dijit", location: DEFAULT_WORKER_URL + "dijit" },
{ name: "dstore", location: DEFAULT_WORKER_URL + "dstore" },
{ name: "moment", location: DEFAULT_WORKER_URL + "moment" },
{ name: "@dojo", location: DEFAULT_WORKER_URL + "@dojo" },
{
name: "cldrjs",
location: DEFAULT_WORKER_URL + "cldrjs",
main: "dist/cldr"
},
{
name: "globalize",
location: DEFAULT_WORKER_URL + "globalize",
main: "dist/globalize"
},
{
name: "maquette",
location: DEFAULT_WORKER_URL + "maquette",
main: "dist/maquette.umd"
},
{
name: "maquette-css-transitions",
location: DEFAULT_WORKER_URL + "maquette-css-transitions",
main: "dist/maquette-css-transitions.umd"
},
{
name: "maquette-jsx",
location: DEFAULT_WORKER_URL + "maquette-jsx",
main: "dist/maquette-jsx.umd"
},
{ name: "tslib", location: DEFAULT_WORKER_URL + "tslib", main: "tslib" }
]
} as any;
Best Practices
When working with CSS, you can load the files directly from your application and let the html-webpack-plugin
and mini-css-extract-plugin
output the CSS file and inject the file location directly into your output HTML file.
// index.tsx
import "./css/main.scss";
// webpack.config.js
...
module: {
rules: [
...
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: false }
}
],
exclude: /node_modules/
},
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
}
]
},
plugins: [
...
// will copy your index.html file
// and inject assets for you
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html",
chunksSortMode: "none"
}),
// will output a css file that you
// imported in your application
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
...
However, if you would like to use the style-loader
to load your styles at runtime, you will need to modify your code.
// index.ts
import "css!./css/main.scss";
// webpack.config.js
...
plugins: [
...
// For plugins registered after the ArcGISPlugin, data.request has been normalized and
// resolved to an absMid and other mappings and aliases have been applied.
// You will need to update the loader plugin appropriately.
new webpack.NormalModuleReplacementPlugin(/^css!/, function(data) {
data.request = data.request.replace(
/^css!/,
"!style-loader!css-loader!sass-loader?indentedSyntax=false"
);
})
...
Please note, we have tested the @arcgis/webpack-plugin
with numerous other plugins, but cannot guarantee that other webpack plugins may not cause some unexpected behavior.