Project Layout

Layouts for javascript projects are all over the map...they vary heavily based on the tooling used. For this book, we are using webpack tooling. Webpack is quite flexible so our layout is not specific to webpack but it is different than most javascript layouts.

Since webpack allows us to build an object graph and the resources can be anywhere, people tend to put static assets into the final destination or close to the consuming "webpack module" instead of aggregating assets by asset class e.g. all images go into a "image" only folder. In the below, instead of keeping our static assets in dist we will just keep them in public and copy them over with a gulp action (or node fs-extra.copy).

Here's an approach:

$ ls myproject
package.js
common.webpack.config.js
misc.webpack.config.js
entityview.webpack.config.js
src
src/EntityView.jsx
src/EntityView.css
src/entityviewimage1.png
src/common.css
src/data/dataaccess.js
src/data/
public
public/publisher_/images
public/publisher_/js
public/publisher_/styles/reset.css
public/publisher_/NonWebpackRelated.html
public/publisher_/NonWebpackRelated.css
public/publisher_/ui/EntityView.html
public/publisher_/ui/EntityView.js
.gitignore
.babelrc
.eslintrc.json

This is just an example, but you can see we keep around a persistent "public" folder that holds assets not managed by webpack although any of those assets could be referenced by webpack at any time and often are.

Also, you may tend to setup baseline webpack configurations in our common.webpack.js and keep asset specific webpack configuration files.

In the above, "misc.webpack.js" would include "common.webpack.js" and add specific configuration information to kick out a "data.js" file into the dist directory that is a library packaging consumable by NonWebpackRelated.html. At the same time, "entityview.webpack.js" could still include "data/dataaccess.js" in its bundling. There are a large number of variations of how you want to bundle the pieces together. A single webpack config can output multiple .js files so you really only need a single webpack config file but they are split-out above for illustratation purposes. Sometimes its easier if you have to inject your components into an existing dist tree and the assets have to be created in multiple locations.

It is not uncommon to have a mixture of react/webpack generated .js files, statically created .html files used in the CRM entity form e.g. include a Web Resource, and .html/.css/.js files that are static and are designed to be included directly in as Dynamics Web Resources.

Since there is alot of mixing of assets across webpack managed and non-webpack managed areas, you should tend towards using the bable-runtime versus babel-polyfill models of polyfilling your browser. babel-runtime is a runtime based approach to polyfill that is library friendly. If you were to include babel-polyfill on a CRM page and have multiple Web Resources on that page, you may find conflict with the the globals that are set by babel-polyfill. babel-runtime and the related babel plugin that goes along with it, was specifically designed to help blend together assets in "library" form that use the polyfills.

The package.json may have several different variations of scripts to run:

"scripts": {
  "misc-dev": "webpack --watch --config misc.webpack.config.js",
  "misc" : "webpack -p --config misc.webpack.config.js"
  "entityview-start": "webpack-dev-server --config entityview.webpack.config.js",
  "entityview": "webpack -p --config entityview.webpack.config.js",
  "entityview-dev": "webpack --watch -config entityview.webpack.config.js" 
}

then you would just do a "npm run-script misc-dev" to keep a continuous cycle of simple .js script updates being created in your "dist" directory. Assuming you had a watcher process that uploads resources as they are changed/created/deleted in the dist/publisher_ directory, they would upload and be usable as they are edited. "npm run-script entityview-start" could start a dev-server and serve hot reload files via a Dynamics/CRM shim---a highly desirable development approach that is described in subsequent sections.

In the above example, there were three scripts for "entityview." Sometimes you may choose to run under hot reload, other times under a "upload webresource" model or other times under a "build a production" version. You choose.

Last updated