TEMPLATE: ES6 | Version Control | NPM | PlayCanvas

TL;DR

Introduction

This is a template project for using ES6 via Babel and WebPack to build PlayCanvas projects.

PlayCanvas is a fantastic open source WebGL Engine and online Editor (which you can get access to for free or pay for an organisational license).

PlayCanvas have developed a shared model that means you can edit your 3D scenes as a collaborative experience with team mates around the office, or around the world - it’s great. They have applied the same to code editing, which is fine for some use cases but imposes certain limitations:

  • No offline access to source code
  • You are stuck with their web editor - which is “ok” but no WebStorm, Sublime or VSCode
  • No source control
  • Someone else can change your file when you aren’t looking and you’ll never know who!
  • No ES6 features, just pure Javascript
  • No NPM ecosystem, meaning you are scrabbling for browserified versions of libraries or more often doing something again or just not bothering

All of this means that it is hard to choose PlayCanvas for serious development projects without going “Engine Only” and that loses you many of the advantages of having a fantastic online editor and layout tool. So now why choose PlayCanvas when Three.js would give you just as much if not more?

The answer has to be to produce code in a proper offline build environment with all the advantages of Babel, WebPack, NPM et al and still be able to use the output in the PlayCanvas online Editor. As no one had done this, and I needed it for a number of projects I took on the task myself. This has lead to a number of NPM repos and a WebPackPlugin that automates most of the process.

Why ES6

If you are asking why you should use ES6 and Babel then I’d say it’s for one simple reason: a programming language should try to get the hell out of your way and let you express what you want.

When we code Javascript for WebGL we are coding for the browser and nearly everything that touches the outside world will be async. Expressing async in traditional Javascript is messy as hell. Try writing a for-next loop that loads a list of things from the web in sequence using Promises or callbacks and it will become immediately obvious. With Babel and ES6 it’s just a loop. Everything else is a christmas tree. Yes it’s possible, but it’s easy to have a hard to spot bug, so you do LESS of it than you would otherwise and refactoring is a scary prospect. That’s not right. That’s damaging your creativity to my mind.


function requestFromUrl(url, info) { return new Promise(/* code */)}

async function getData() {
    let urls = ["https://blah1.org", "https://blah1.org/blah", "https://blah2.org/blah/blah"];
    let data = "";
    for(let i = 0; i < urls.length; i++) {
        data = await requestFromUrl(urls[i], data);
    }
    return data;
}

I know this is a contrived example, but this “kind of thing” happens all of the time in my developments, and they
are better for me being able to implement them easily. Write that as just promises or callbacks and it will be illegible to most developers without a lot of study.

ES6/ES7 etc exist to create a better programming language for the web, I say let’s use it.

Not many browsers support ES6 let alone ES7

That’s what Babel is for, if the browser doesn’t support something, it provides that support for you. Plus it compiles your ES6 to ES5.

In addition this template project lets you specify which versions of browsers you are supporting and Babel only does what it has to. You could even simply build different versions for different browsers (or ages of browser etc) if you prefer!

Why NPM

If you need some standard function, algorithm or procedure there’s a good chance that there is tested code out there to install with one line of shell script.

Why WebPack

WebPack is going to make building all of this and serving it to your browser an automated process.

Getting Started

The shortest way to get started is really simple.

Prerequisites

You must have a version of Node and NPM installed.

You can get that from here.

Installing the template project

Make a directory and change to it

npm install babel-playcanvas-template

Now in [YOUR_DIRECTORY]/node_modules/babel-playcanvas-template are all of the files you need. Either
develop in there or copy that whole directory structure somewhere you want to develop.

The entry point - which is where you will import your own code - is in src/main.js

In the template this imports a bunch of PlayCanvas extensions and then a single
example.js script that uses a couple of ES6 features for a demo.

Writing your own code

Create a file in src or a sub directory and script what you like. Just make sure that it is imported by main.js (note that paths are relative to src and must start with a ./). When you start developing things that import each other, you just need to make sure that something in main.js imports something that imports the code you add!

If you find that something didn’t show up, that’s probably why.

Building, debugging and testing your code

Firstly we need to make a configuration file - there’s an example called config.example.json.

The config file is in the root of the project (the parent of src) and needs to be called config.json. This will eventually also control the automatic upload of your code to PlayCanvas, but to start with, just copy the example to config.json.

You can build your code using either webpack or an automated process with npm.

So typing npm run build in the root folder of the project (the parent of src) the template will build a production version of your code into the build folder.

Either build your code with NPM

npm run build

Or build your production code with webpack

webpack --config webpack.production.config.js

The output file will be called main.build.js. To use that in PlayCanvas just drag and drop it onto the PlayCanvas editor for your project.

Now open your developer tools in the browser with the PlayCanvas Editor open and in the Javascript console type

config.accessToken

Copy the result of this and paste it into the config.json file as your bearer token.

Then in the javascript console type

config.project.id

And put that in the project id part of config.json

Finally if you haven’t already done it, drag main.build.js and drop it in the PlayCanvas assets window.

When it’s imported click on it and in the properties window on the right, take it’s ID and put that in config.json as your assetId.

Now every time you run npm run build it will upload the result to PlayCanvas for you.

Local serving your development build

There’s a better way to do ongoing development though, you only really need to upload your build when the attributes of something change, you add a new script or you want to publish your build.

This template project has a solution for that too. You will be able to see all of your source code in your developer tools when you use any means of making a development build.

Loading Screen Method

If you have a loading screen or can make one then you can use either the whole script in utility-scripts/loading_screen_scripts_2_0.js or add the utility-scripts/exerpt.js to the top of your own.

This will allow you to serve files locally if you add a ?local=http://localhost:8081 to your launch url query string AND you change the protocol of the launch page to be http. If you really need https then see the section later on how to do that instead.

PlayCanvas Script Method

This is less reliable. Create a script in PlayCanvas Editor. Copy utility-scripts/exerpt.js
into it and set it’s loading order to be before main.build.js.

See the instruction about the URL in the previous section on how to modify your launch to use it.

Starting the server

Now you can type npm start in the project root. This will, build and upload your code, then start a local server to serve any changes you make. When you change your code, your launch window will automatically update.

If you need to upload again, just stop the server with CTRL+C and type npm start again. Then refresh your launch and Editor windows.

Development builds without local serving

Type webpack --config webpack.development.config.js to build and (if configured) upload a development version of your code which will have source mapping to make it possible to see your own code when you debug.

Production Build

Just type npm run build any time you want a production build.

Production builds are minified and don’t have source maps embedded (they are a separate file).

Using NPM

You can just use NPM like normal. Basically find the module you need and type

npm install --save <module-name>

You can then import it into the file you need it in by adding an import statement at the top of your file.

import blah from 'blah-module';

...

blah(something); 

You may also use require syntax if the whole file is written that way.

Targeting different browsers

config.json also contains a "browsers" entry - this is a query in the browserslist format that tells Babel what it needs to augment in the target output. By default it’s set to > 1% which means that the output code will work on 99% of browsers in the field.

If you set it to last 2 Chrome versions then a lot more of ES6 is implemented already and there will be less work done, so a smaller output file (and possibly some code could be faster).

Using this method you could actually create multiple builds and choose between them.

Conclusion

Hopefully this will get you started using ES6 and modules with PlayCanvas. Feel free to ask for @whydoidoit on the PlayCanvas forum if you want to discuss.

Enjoy!

- Ends -


HTTPS serving

You can configure webpack to HTTPS serve instead of HTTP.

Use npm run https to start your local development build. Then:

  • Either: in a separate window navigate to https://localhost:8081/main.build.js and if you are warned it isn’t safe, just proceed anyway. This will mean that you always see that the launch page is untrusted and may cause other issues, it’s normally fine for me.

  • Or: get your browser to trust node_modules/webpack-dev-server/ssl/server.pem. This can be easier said than done. You can also replace server.pem with your own trusted localhost certificate. Just you’ll have to pack it as a .pem file.
    (On Apple by default it will be a .p12, Google for how to change it).

Don’t forget to change your launch URL and the local parameter ?local=http://localhost:8081 to HTTPS!!

Personally I’ve used Certificate Tools to make certs that work. Make sure you sent the Subject Alternative Name(s) DNS to localhost as well as Common Names. It also provides you with a thing to run to pack .p12 into a .pem after you’ve generated your certificate. It only took me about 5 tries to work out what I had to do with it!

7 Likes

As an engine user, I really like your awesome works!

1 Like

Thanks!! very kind of you to say so :slight_smile: It took 24 github repos to make all of this in the end lol. But I’ll be able to use it myself on lots of things so - no biggy.

1 Like

This is heavenly sent!

Thanks a lot Mike for the ongoing contributions.

Taking Playcanvas to a whole different level of production.

I’m quite new to the web development pipelines. Am I right in saying that there’s a script/process in this tool that uploads the project source (ie PlayCanvas Components) to the project on the PlayCanvas servers?

There is a WebPack plugin that does that yes. https://github.com/whydoidoit/playcanvas-webpack-plugin

1 Like

Just wanted to add the following to my reasons for doing this project…

I want anyone to be able to come along and add a shader I wrote by typing npm install --save playcanvas-ssao-shader or to add my multithreaded nav mesh generator and follower using npm install --save playcanvas-a-star (those aren’t there yet but they will be soon). Why do I want that? Because in a few months time I want to type npm install --save that-thing-mike-didnt-do and benefit from a community building this stuff :slight_smile:

One thing I’d like to mention here is that the assets REST API is not yet meant to be used by third parties so it might change or stop working without notice.

We are looking into making it available but don’t have an ETA yet!

1 Like

Yeah understood. It’s just working off what the editor does at the moment. If it did stop working then:

  1. Either: You can drag and drop the build file
  2. Or: Someone can fix the plugin :slight_smile:
1 Like

I always wonder why PlayCanvas is not so much popular, like other solutions.
Because it is great, I really love it.

And I hope you just answered my question - people were need to use it with new web standards and technologies.

Thanks for this great work!

Agreed it is by far my favourite tool and for ages I’ve crammed it into my workflow while cursing the fact I keep having to browserify bits of my other code or write them again and I feel like I’m in a time warp writing ES5 async code :slight_smile:

I mean, with the advent of these instant games in Messenger and the ubiquity of the web, I think it is a real choice against Unity for proper game development especially for mobile devices.

Where it’s lacking of course is:

  • Mecanim (ok I’m trying to fix that over time with Blend!)
  • Physics - an emscriptem port of anything is a bit of a nightmare until you can tell emscriptem that garbage collection is a total no-no - (ok so my Collision thing fixes this for me, but limits what I can write - one day I’ll have time to build that ground up physics engine).
  • Navmeshes and path following
  • A customisable editor or an open source editor, having one that is neither has been a real issue, we have dozens of Unity editor extensions - so I finally bit the bullet and built a proper extension, before PCE+ I had bits of code I’d drop in but no framework or way to easily distribute it to the team.

But for me the biggest single thing is that Scripts 2.0 had some lovely features but felt like it was making the whole system more of a “toy” with no source control. Collaborative coding or pair coding is great in certain circumstances but hardly a respected coding practice across large projects. Where is the TDD? The code review? The pull requests? I mean make the PlayCanvas Engine project be editable at any time by anybody you at sometime approved and it would sink into a bug ridden disaster.

I did have a sudden “Eureka!” moment when I realised I could use scripts 2.0 to manage the output of a proper build process and sudden get all of the features I wanted. Suddenly this is a tool that I can convince my team isn’t a thing we should use “when we have to”. We avoided 7 different developments on PC over the last 18 months in favour of poorer Pixi or HTML alternatives. We build 2 in PC. We could just have used the Engine, but like I say, that’s shooting yourself in the foot (and surely can’t help PC’s business model). No way I’m convincing people to give up Unity’s cycle speeds or building our own level editors.

I guess that my use case isn’t the “standard PlayCanvas user use case” but I’d argue that if more people had our needs for PC then it would significantly boost the usage and change the popularity immensely.

I’ve met a bunch of the PlayCanvas team a year or so back, they are super smart people, I certainly don’t want to second guess them. I’m hoping that this thread will lurk around the place and mean that developers or teams that come across PC but silently reject it because of the restrictive development architecture will read it and come on board. My second hope is that people really use this and we do get a growing community of npm packages for PC. It would totally revolutionise how people made choices for mini game development and probably how they chose for major projects too.

I guess the thing is that this forum is a community, but it’s a village, probably a hamlet. It needs to grow and push real discussion and revolution. People choose Unity because of the hugely supportive community. I know I did and thoroughly enjoyed being an active part of that community. But the Unity product is totally unfit for the purpose I have - mobile devices running HTML5/WebGl/Javascript.

[Rant ends]

7 Likes

+1 for the lack of version control. This is really important. When writing code with others, you can not do “code review”, especially when the project become large, the code base will become mess without version control.

Another thing I want to say is that the web based code editor is too poor, and without plugins I used in other editor(vim / sublime text). Can you guys provide plugin mechanism for the code editor ? Or provide api to let users upload scripts, that means we can use our favourite editor and use git/svn by ourselves.

1 Like

Well this template lets you do that…

Yes, I know. :smile: Although the implementation is based on something internal. I mean playcanvas team should consider exposing api for developers.

1 Like

Yeah it’s been on the cards for a while I think… I just looked at the editor code and saw how they did it.

I finally got this working but seems like when i try to update some code, the launch window shows an old version of the script. The server seems to have the correct one though.

Webpack compiles successfully if i make any changes, yet playcanvas shows an old version. Only way I can get this to work is by re-running npm run start which is much slower…

You’ve got the localhost thing running with the loading screen or startup script so it’s reading locally?

Check the network tab to see if it is getting it from there

Might want to have dev tools invalidate the cache

Ive got the local host thing running with the loading screen script.
this is what my network shows:

Can see your url (passing local=)? It;s not loading from local, it’s loading from pc