Migrating to the new iModel.js Application Build System

The iModel.js 1.0 build system all applications relied on a single package (@bentley/webpack-tools) to build iModel.js backends, frontends and extensions. With the release of 2.0, there are significant improvements to the build system to help with both clarity and usability to enable creating an app based on the latest technologies easier. To aid in this, the build system is now split into 3 separate components:

  • The general build tools still reside in the @bentley/build-tools package.
  • iModel.js Extensions (formerly Plugins) are now bundled using Webpack with @bentley/extension-webpack-tools
  • The iModel.js frontend build system is now based on Create-React-App.

Background on the switch to Create-React-App

Create-react-app (CRA) is one of the most popular ways to start writing React applications and is maintained by Facebook (the creators/maintainers of React). There are many more details about CRA and how it works on their website.

The main part of create-react-app's build system is the package react-scripts which holds all of the webpack/build configuration that is used by CRA and therefore most react-based applications. In order to support iModel.js applications, a fork has been created of the create-react-app repository specifically for a few changes to the webpack configuration in react-scripts. For more information on the exact changes made in the fork, and why they were considered necessary, check out the README.

One of the main principles of CRA is in the source tree of the app there is a src folder with an index.ts at the root of the folder, as the entry point of an app, and a public folder with a index.html at the root.

Everything within the src folder is included in the webpack process, including all of the assets that are parsed via loader (i.e. scss, css, json, etc.), and everything in the public folder is expected to live at the webroot when it's deployed so it's copied into the build output appropriately.

Step by step guide

With the above background in mind, the quickest/easiest migration pattern for all existing apps that are currently using the iModel.js module system is broken down into the following set of steps.

  1. Add a dependency on @bentley/react-scripts and remove the dependency on @bentley/webpack-tools
    • This is the aforementioned fork of the create-react-app webpack configuration
  2. Move the current index.html, that now most likely lives within src/frontend/index.html, to public/index.html.
  3. Update the index.html to remove the following lines,

     <!-- check the browser to verify it is supported. -->
     <script type="text/javascript" src="v<%= htmlWebpackPlugin.options.loaderVersion %>/checkbrowser.js"></script>
    
     <script type="text/javascript" src="v<%= htmlWebpackPlugin.options.runtimeVersion %>/runtime.js"></script>
     <script type="text/javascript" src="v<%= htmlWebpackPlugin.options.loaderVersion %>/IModelJsLoader.js"
     data-imjsversions='<%= htmlWebpackPlugin.options.imjsVersions %>'></script>

    and replace them with,

     <script type="text/javascript" src="%PUBLIC_URL%/scripts/checkbrowser.js"></script>
  4. Add a src/index.ts file with an import to the current entry point of the app within src/frontend. For example if the entry point is currently ./src/frontend/index.ts, then the new ./src/index.ts will be as simple as the new ui-test-app/src/index.ts file.

  5. Remove the iModelJs.buildModule from the build script in package.json and replace call to buildImodelJsModel with react-scripts build.
  6. Add a browserslist section to the package.json
     "browserslist": [
       "electron 6.0.0",
       "last 4 chrome version",
       "last 4 firefox version",
       "last 4 safari version",
       "last 4 ios version",
       "last 4 ChromeAndroid version",
       "last 4 edge version",
       "not dead",
       "not <0.2%"
     ]
  7. Add a separate tsconfig.json for backend build called tsconfig.backend.json.
    • The build between the frontend and backend are now slightly different in their configuration meaning that an app now needs two separate tsconfigs
    • The contents of the tsconfig.backend.json should be similar to the following:
      •  {
           "extends": "./node_modules/@bentley/build-tools/tsconfig-base.json",
           "compilerOptions": {
             "target": "es2017",
             "module": "commonjs",
             "outDir": "./lib"
           },
           "include": [
             "./src/backend/*.ts",
             "./src/common/*.ts"
           ],
           "exclude": [
             "lib",
             "node_modules"
           ]
         }

FAQ

Last Updated: 23 April, 2020