node package manager

generator-azure-web-app

Azure Web App Yeoman

generator-azure-web-app

npm version Node.js dependencies npm downloads

Deploy to Azure

Minimalist Azure Web App generator: Webpack/Rollup + React + Express, deployable to standalone Node.js, Azure App Service, and IIS.

Why us?

Modern websites are not just bunches of plain text files. Build process increases page load efficiency and overall page performance.

But everyone build and promote their own build process. There are few reasons you should choose us:

Try it out in 3 easy steps

  1. Fork this repository
  2. Click Deploy to Azure
  3. Push your changes and see it continuously deploy to Azure

It takes about 5-10 minutes for the first build, have a little patience.

How to develop professionally

  1. Create a new Web App project
  2. Run local development server
  3. Develop locally
  4. Prepare for production deployment
  5. Deploy to target servers
  6. Update the scaffolding

Create a new Web App Project

For the very first time, run npm install -g yo generator-azure-web-app to install Yeoman and our scaffolding.

Run yo azure-web-app to create a new project.

Run local development server

Run npm start, the development server will listen to port 80 and available at http://localhost/.

To change the port to 8080, either set environment variable PORT to 8080, or run npm start -- --port 8080.

Develop locally

If you added new packages or modified server code, don't forget to restart the development server to pick up new changes.

Prepare for production deployment

Run npm run build, to bundle JavaScript files, crush images, etc. It outputs to dist/website/.

Optional: Using Rollup as bundler in production mode

Instead of Webpack used in development, you can opt for Rollup as bundler for production, it has better tree-shaking mechanism, thus smaller output file size.

Using rollup as bundler is experimental. Please file us an issue if you run into any problems.

There are few ways to select your bundler:

  • Run npm run build -- --bundler rollup for one-time switch
  • Set environment variable NPM_CONFIG_BUNDLER to rollup or webpack
  • Modify .npmrc and set bundler = "rollup"
  • During Yeoman scaffold, set bundler to rollup

Deployment

The project supports multiple deployment scenarios, we will cover each separately.

Don't forget to build your project before deployment, run npm run build.

Deploy as a standalone Node.js

Run node dist/website/app.js to run as a standalone Node.js.

To deploy to your SaaS provider, copy everything under dist/website/ to your provider.

Deploy to Azure App Service

Azure App Service support continuous deployment or traditional MSDeploy. For small teams, we recommend continuous deployment.

Thru continuous deployment

Azure Web App comes with handy continuous deployment feature. When you push/save your code, Azure Web App will pickup new changes from GitHub, local Git (hosted on Azure), Dropbox, OneDrive, etc.

Follow steps below for first time setup for GitHub deployment.

  1. Commit your project to GitHub
  2. Browse on GitHub
  3. Click Deploy to Azure

When deploying using continuous deployment, the project will build on Azure via Project Kudu.

Because the build is done on Azure, we modified the virtual path from /site/wwwroot to /site/wwwroot/dist/website. This is done by customizing azuredeploy.json.

Thru Visual Studio Team Services

Deploy thru Azure continuous deployment is limited and asynchronous. This makes the option not ideal for medium or large teams.

We recommend VSTS Release Management for advanced deployment, it also comes with BVTs, performance tests, approval process, rollback, etc.

You can follow steps for VSTS here for advanced deployment scenario.

Thru MSDeploy

If you use CI/CD tools other than Azure and VSTS, you may want to integrate with MSDeploy.

  1. Run npm run build to build the project
  2. Run npm run pack to pack the deployment as a MSDeploy ZIP file
  3. Download publish settings file, either from Azure Dashboard or using Azure PowerShell
  4. Run npm run deploy -- --publish-settings=yoursite.PublishSettings to deploy with MSDeploy

To use a specific version of Node.js, don't forget to modify iisnode.yml manually.

Deploy to Docker

If you use Docker for deployment, depends on your scenario, you can select one of the supported Docker image types:

Run docker build . at the project root to build your docker image.

Deploy to IIS

You can also deploy the project to an on-premise or hosted IIS.

  1. Make sure Node.js and iisnode is installed on the target server
  2. Run npm run pack to pack the deployment as a MSDeploy ZIP file
  3. Use MSDeploy to deploy your package

The following MSDeploy command-line switches can be used to deploy the package to an IIS box.

"C:\Program Files (x86)\IIS\Microsoft Web Deploy V3\msdeploy.exe"
  -verb:sync
  -source:package="dist\packages\web.zip"
  -dest:
    auto,
    ComputerName="https://<server>:443/msdeploy.axd?site=<appname>",
    UserName='<username>',
    Password='<password>',
    AuthType='Basic'
  -setParam:name="IIS Web Application Name",value="<appname>"

Update the scaffolding

We update our scaffolding from time to time. To update your existing project, rerun yo azure-web-app and scaffold again. Yeoman will automatically the scaffolding from npm.

Don't worry, Yeoman will prompt to overwrite a file if it should be replaced.

Support Internet Explorer 8

Although the user base of IE8 is fading, in some cases, you may still need to support older browsers.

Disable hot module replacement on development server

Run npm start -- --hot false to start a development server without hot module replacement.

Use react@^0.14 and add es5-shim

You can copy the following code into index.html.

<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-sham.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/console-polyfill/0.2.3/index.min.js"></script>
<script src="https://unpkg.com/react@0.14/dist/react.min.js"></script>
<script src="https://unpkg.com/react-dom@0.14/dist/react-dom.min.js"></script>

Look for IE8-friendly NPM packages

Some NPM packages are not IE8 friendly. For example, fetch does not support IE8. You may need to use fetch-ie8 instead.

Moreoever, some packages might be pre-transpiled, they might not have reserved keywords properly escaped. There are two ways to tackle this issue:

  • Contact package developer and kindly ask them to either
    • Add module in package.json and reference to non-transpiled version of code, or,
    • Escape reserved keywords during transpilation
  • Use Webpack instead of Rollup: our Webpack workflow is configured to escape reserved keywords even in node_modules/ folder

Roadmap

These are items we are working on or under consideration:

  • Add pngout to npm run build
  • Continuous deployment on Azure App Service
    • npm install should build
    • .deployment file for Kudu to specify project folder at dist/website/
  • Scaffold with Yeoman
  • Use a single package.json if possible
  • Host development server programmatically
  • Bundle using Rollup
  • Uglify production bundle.js
    • Uglify Rollup build
    • Uglify Webpack build
  • Steps to deploy from VSTS Release Management
  • Try out on App Service for Linux
  • Upgrade to Webpack 2
  • Move development server code out of /dist
  • Reduce the codebase
    • Move to a popular configuration package, e.g. config
    • Consider remove gulp clean and gulp rebuild
  • Sample code for server-side rendering
  • Include Jest and npm test script
  • Consider glamor for CSS bundling
  • Consider restify in addition to Express

Roadblock on App Service for Linux

Because we cannot modify virtual path on Linux, thus, continous deployment is currently not supported on Linux. We will continue evaluate the possibility to CI/CD on Linux.

One possible solution is to re-architect the project so the output is in-place rather than under /dist. But downsides:

  • Difficult to package the website as MSDeploy ZIP file

Roadblock on unifying package.json

Originally, we planned to have a single package.json and packages for server code are marked as direct dependencies and browser code are marked as development dependencies. But few things:

  • We want to separate list of server-only packages
    • This helps minimize the final output file size, i.e. no Webpack or Babel in server-only packages
  • But the problem is, Azure Web App deployment script (a.k.a. deploy.cmd) will run npm install --production only
    • We don't want to customize deployment script and maintain versions of deploy.cmd
    • We need to build browser code and we need to run npm install --only=development on postinstall
    • Thus, we need to use --ignore-scripts to hack
    • Also, it doesn't quite make sense for npm install --production to install both production and development packages
    • --ignore-scripts broke some packages, e.g. optipng-bin

Thus, we decided to have two package.json, one in root for browser code (e.g. Babel + React), another in lib for server code.

Roadblock on enabling hot module replacement on Internet Explorer 8

We tried very hard to bring hot module replacement to IE8 but it deemed impossible. We learnt a few things though:

FAQs

  1. After deploying to Azure Web App, it say directory browsing is not allowed.
    • During first deployment, do not browse to the web site until the deployment is ready. Otherwise, it will show 404, until you restart the server.
  2. How about CSS/LESS/SASS?
    • We believe bundler should only bundle JS files and not CSS or other assets. Thus, we did not preconfigure the scaffolding with style-loader
    • For modern CSS inlining, we prefer glamor or aphrodite. Please note that IE8 might not work with these modern CSS inliners

Contributions

Like us? Star us.

Want to make it better? File an issue to us.

Working on this scaffolding

If you want to develop or debug this scaffolding, follow these steps:

  1. Run npm uninstall generator-azure-web-app -g to uninstall any installed scaffolding
  2. Run git clone https://github.com/compulim/generator-azure-web-app.git to clone the repository
  3. Run npm link . to link-install this copy, instead of the official one from npm registry

Next time, when you run Yeoman to generate a new azure-web-app project, it will use your copy of scaffolding you cloned.