olsibob

Hot reload / Fast iterative dev with typescript + webpack?

Recommended Posts

Hello, I'm just getting started with babylon.js. I've used node on the backend before, but I'm new to using it on the frontend with webpack, it's also my first time using typescript. I'm using Visual Studio Code as my IDE.

I'm looking for tips for creating a development environment that will allow fast, iterative development. I'm aware that TypeScript involves transpiling, so perhaps it's not quite a "hot reload", but "pretty quick reload" would be great. In addition, I sometimes work offline, so everything needs to be able to run locally.

At the moment I just have a super simple scene for testing purposes, held in a single `main.ts` file. Everything builds and runs as it should, but the build process can be very slow. I have a few questions

  1. In particular, the step that can take a minute or so is `92% chunk asset optimization UglifyJSPlugin`. I'm not sure what is running UglifyJS, it's not something I've specified in my build steps. Is it possible to disable it for non-production builds? (not that I've got as far as setting up anything like environment variables).
  2. Given that my `main.ts` is so simple, it feels like it must be running uglify on the whole of babylonjs. Is it possible to just transpile the files that have been changed?
  3. Is it really necessary with the webpack workflow to bundle everything into a single file? (I thought that if a user was navigating between several sites using babylonjs, the browser might cache babylonjs? Wouldn't it bundling everything into a single file block this caching)?
  4. Any other tips for speeding up builds/ creating a nice, speedy dev environment?

webpack.config.js:

const path = require('path')

module.exports = {
    entry: {
        'project': './src/main.ts'
    },
    output: {
        filename: '[name].js'
    },
    resolve: {
        extensions: ['.ts', '.tsx', '.js']
    },
    devtool: 'source-map',
    plugins: [
    ],
    externals: {
        oimo: 'OIMO', //why do I need to declare this as external if it's included with the npm install?
        cannon: 'CANNON', //or true
        earcut: 'EARCUT'
    },
    module: {
        rules: [{
            test: /\.tsx?$/,
            include: path.resolve(__dirname, "src"),
            loader: 'awesome-typescript-loader', // I've tried ts-loader too
            exclude: /node_modules/
        }]
    }
}

tsconfig.json:

{
    "compilerOptions": {
        "target": "es6",
        "module": "commonjs",
        "noImplicitAny": true,
        "sourceMap": true,
        "outDir": "app",
        "types": [
            "babylonjs"
        ]
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "node_modules"
    ]
}

package.json

{
  "name": "babylondemo",
  "version": "1.0.0",
  "description": "",
  "main": "main.ts",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --progress -p",
    "watch": "webpack --progress --watch"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "babylonjs": "^3.2.0",
    "babylonjs-loaders": "^3.2.0"
  },
  "devDependencies": {
    "awesome-typescript-loader": "^5.0.0",
    "typescript": "^2.8.3",
    "webpack": "^4.8.3",
    "webpack-cli": "^2.1.3"
  }
}

 

Share this post


Link to post
Share on other sites

FYI,

I am not using webpack directly. Instead I am using angular which uses webpack under the hood.

With angular it is quite easy to configure both release and debug build (which allows fast build and watch + auto browser refresh).

Share this post


Link to post
Share on other sites

@Deltakosh thanks, that document is super helpful. Perhaps there should be a doc that is explicitly aimed at "environments for developing using BabylonJS", in addition to this one on contributing to BabylonJS? (I would of course eventually like to contribute, but I need to get to know it first). I don't think what I'm doing is specific to vscode's handling of tyoescript, I think I'd get similar results in Atom.

@HoloLite thanks for the suggestion about Angular. That led me to the Angular docs, which has one of the nicest introductions to webpack I've found. https://angular.io/guide/webpack#entries-and-outputs it's for webpack 3, but it wasn't too painful to update it for webpack 4.

I think part of the issue I've been having is that the js ecosystem evolves so fast that even tuorials that are a couple of months old can be out-of-date. I think I've found solutions to some of my problems. I've got some fairly nice results (as in fairly fast reloading) by taking these steps

1. The main one is that I'm using webpack 4 (but was following webpack 3 tutorials). 4 introduces support for environment modes, and the default is `production`, which runs the minification step https://medium.com/webpack/webpack-4-mode-and-optimization-5423a6bc597a. Additionally, my npm build script was invoking webpack with the -p flag, which also sets the environment to production. So this was why minification was running even though I had an empty plugins array. By creating a config that runs webpack in development mode, I can skip minification.

2. using the webpack-dev-server really helped here

3. Splitting the output bundles into app (my tiny main.ts file) and vendor (babylonjs), with the splitChunks optimization seems to help as well

I'm sure there are many more refinements I could make. 

What I might do is create a WIP GitHub repo of the setup I have. 

Can anyone recommend any repos that demonstrate their development setup?

I'm keen to get a fairly solid development environment in place, so I'd like to get an idea of what "good" looks like. How do other forum users use BabylonJS with typescript?

Edited by olsibob
add link

Share this post


Link to post
Share on other sites

I have a template to configure minimal angular with babylonjs which also includes the npm packages and how to reference the ts api from your ng ts files. If I find my free time again I will upload it for the forum. In fact you can easily expand this to make a HTML tags/element based Dom model api for babylonjs. And you can combine both Dom style and procedural approach. I am not much of Dom person so I never bother going there even though it's really not too hard to do it. 

Yes the webpack dev server is best for dev env. It autobuilds and auto refreshes the browser for debug build. No need to configure gulp/grunt etc. 

Share this post


Link to post
Share on other sites

I think I've got a setup now that I'm happy with. It automatically reloads pretty quick (usually before I've had time to cmd-tab back to the browser), and requires IMO minimal setup. The key was realising that webpack 4's "mode" variable pretty much takes care of everything for you, and can be passed in from the npm scripts, so there's no need (for small projects anyway) to have different config scripts for different environments.

Here you run npm start for develop mode with hot reloading, and npm build for production.

Here are the config files:

package.json

{
  "name": "babylondemo",
  "version": "1.0.0",
  "description": "",
  "main": "main.ts",
  "scripts": {
    "start": "webpack-dev-server --mode development --inline --progress --port 8080",
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode production --progress",
    "watch": "webpack --progress --watch"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "babylonjs": "^3.2.0",
    "babylonjs-loaders": "^3.2.0"
  },
  "devDependencies": {
    "awesome-typescript-loader": "^5.0.0",
    "html-webpack-plugin": "^3.2.0",
    "typescript": "^2.8.3",
    "webpack": "^4.8.3",
    "webpack-cli": "^2.1.3",
    "webpack-dev-server": "^3.1.4"
  }
}

tsconfig.json

{
    "compilerOptions": {
        "target": "es6",
        "module": "commonjs",
        "noImplicitAny": true,
        "sourceMap": true,
        "outDir": "app",
        "types": [
            "babylonjs"
        ]
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "node_modules"
    ]
}

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: {
        'app': './src/main.ts',
        'vendor': './src/vendor.ts'
    },
    externals: {
        oimo: 'OIMO', //or true
        cannon: 'CANNON', //or true
        earcut: 'EARCUT'
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: 'src/index.html'
          })
    ],
    module: {
        rules: [{
            test: /\.tsx?$/,
            include: path.resolve(__dirname, "src"),
            loader: 'awesome-typescript-loader',
            exclude: /node_modules/
        }]
    }
}

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.