Consider building ESM for browser.
MicahZoltu opened this issue · 10 comments
TL;DR: For ES modules to work in a browser, import statements need the .js
extension on them. https://github.com/Zoltu/typescript-transformer-append-js-extension/ is a a TypeScript transformer that will do that for you automatically during build.
For a detailed description of the problem see the Motivation section of https://github.com/Zoltu/typescript-transformer-append-js-extension/. For a solution, see the Usage section of the same repository.
Ah, it appears you are using webpack to generate ES modules out of ES5 modules compiled down from TypeScript. I'm not sure how to fix the problem with Webpack.
AppRun does support ESM in the browser. See the example: https://glitch.com/~apprun-lit-html
Checkout the V2 branch, where it uses rollup in addition to webpack.
It doesn't work natively in the browser using ES modules. It currently has to be run through a bundler first, such as Rollup or Webpack, as you described. However, if the import statements have a .js
suffix added to them, then it will work in a browser natively, without any bundling. You can just do
<script type='module'>
import { apprun } from './vendor/apprun'
...
</script>
and it will work.
First, I think the bundler is necessary. Take a look at the example: https://apprun-lit-html.glitch.me
There are many files for lit-html, but I prefer to have just one file for AppRun.
Second, to use ESM in the browser, it does require the .js extension as you mentioned. However, it also requires the module references must start with either "/", "./", or "../".
// NOT WORKING IN BROWSER
import { app, Component } from 'apprun';
export default class extends Component {
//
}
// WORKS IN BROWSER
import { app, Component } from '/_modules/apprun.js';
export default class extends Component {
//
}
I have created another tool to solve the problem, which does two things:
- It copies the modules from the node_modules directory to the /_modules directory.
- Fix the module references to use the newly copied file.
The tool can be found at https://github.com/yysun/apprun-site/blob/master/cli-esm-fix.js
import { app } from 'apprun'
is solved with import maps, which is coming to a browser near you "soon". 😉
There is a polyfill for it that allows you to use it in ES module supporting browsers today, which is what I'm using for all of my new projects.
As for the "many small files", this is largely solved with HTTP/2 server using HTTP/2 push tech. When properly configured, the user will submit a GET request for index.html, and the server will reply with index.html and any other assets that will be immediately needed. When the browser renders the page, it will already have the files fetched so there are no extra round trips.
This is all to say that I believe bundling is "on the way out", though it may take a long time for it to fully die off (and import maps aren't live in any browsers yet). However, I always try to encourage projects to support new tech sooner rather than later so web developers can move on to it sooner rather than later.
Totally agreed, we should support future technologies.
In the apprun@latest release, the apprun.js is the UMD and ES5 build.
In the apprun@es6 release, the apprun.js is the UMD and ES2015 build. The apprun.esm.js is the ESM and ES2015 build, which is defined as pkg.module.
I hope someday I can make apprun@es6 as the default and latest.
I just pulled down apprun@es6
to try it out, unfortunately it still has extensionless imports so it doesn't work natively in browsers. 😢
You can use the apprun.ems.js in the browser.
<script type="module">
import { app } from '/[path]/apprun.esm.js'
</script>
Or from CDN
<script type="module">
import { app } from 'https://unpkg.com/apprun@es6?module';
</script>
Ah, I didn't notice the pre-bundled ESM module. It still would be nice for the unbundled ESM module to work in browser natively, but this is good enough for my needs. Thanks!
If you really want unbundled modules, try this
<script type="module">
import { app, Component } from 'https://unpkg.com/apprun@es6/esm/apprun?module';
</script>
unpkg.com can serve the modules dynamically by using the ?module parameter.