Script load order

Indeed Typescript is a life-saver for people coming to Javascript from C# or any other strongly typed language.

Here is how I configure my projects, when doing TS development, to have a clean (and debug enabled) build.

My tsconfig.json during development:

{
  "compilerOptions": {
    "target": "ES2015" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
    "module": "none" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
    "outDir": "./dist" /* Redirect output structure to the directory. */,
    "rootDir": "./src/" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
    "strict": true /* Enable all strict type-checking options. */,
    "typeRoots": [
      "types"
    ] /* List of folders to include type definitions from. */,
    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
    "inlineSourceMap": true /* Emit a single file with source maps instead of having a separate file. */
  }
}

This will indeed produce several files, one for each .ts source file. For small projects this might be OK, for larger it starts to get slow and messy having to upload several files to your Playcanvas project.

Webpack to the rescue, this will take care of building the .ts project on each file change and upload a single file (that can contain multiple pc.Script types) to Playcanvas.

Here is my webpack.config.js, there are plenty of tutorials online on how to configure webpack to work with typescript (shoot if you have any question!):

const path = require("path");

module.exports = {
  entry: "./src/index.ts",
  mode: "development",
  module: {
    rules: [
      {
        test: /\.ts?$/,
        use: "ts-loader",
        exclude: /node_modules/
      }
    ]
  },
  resolve: {
    extensions: [".ts", ".js"]
  },
  output: {
    filename: "ermis-special-effects.js",
    path: path.resolve(__dirname, "dist")
  }
};

Webpack requires an entry point to your Typescript application, which in a Playcanvas context means your code should be running at least one instance of a pc.createScript() method automatically (the editor parses your JS code searching for these declarations).

On how to define your Playcanvas scripts in Typescript: I don’t do anything fancy yet, I opt to use any and standard JS methods:

const PositionEntity: any = pc.createScript("positionEntity");

// initialize code called once per entity
PositionEntity.prototype.initialize = async function() {
  const entity: pc.Entity = this.entity;

  for (let index = 0; index < 10; index++) {
    entity.translate(1, 0, 0);

    await sleep(150);
  }
};

// update code called every frame
PositionEntity.prototype.update = function(dt: number) {};

// --- Utilities
function sleep(ms: number) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
1 Like