No
Everything described in this article.
But for lazy ones I'll add some highlights here.
<!-- Browsers with ES module support load this file. -->
<script type="module" src="main.js"></script>
<!-- Older browsers load this file (and module-supporting -->
<!-- browsers know *not* to load this file). -->
<script nomodule src="main-legacy.js"></script>
Warning! The only gotcha here is Safari 10 doesn鈥檛 support the nomodule attribute, but you can solve this by inlining a JavaScript snippet in your HTML prior to using any
Wow @neeharv and I were literally just discussing this article and I came here to post this. This is an amazing idea鈥攊t feels like <script type="module"> finally gives us a good point to separate new browsers from the old.
Thinking of an approach with env = 'module' on babel-preset-react-app and do a separate build. Have to figure out where the output would go to though.
My thoughts about this:
InterpolateHtmlPlugin and HtmlWebpackPlugin from both configs and use node/grunt/gulp api to generate html file with script/link tags.Or add webpack plugin like unminified-webpack-plugin that will convert all modern js files to ES5 style.
/cc @addyosmani
I recall seeing a tweet that this is horrible for performance.
Can you shed some light? Thanks!
Ok, after a few hours of hacking, this is what we've found:
This feels like the nicest idea, where you now have two entry points (in webpack.config.prod.js):
- entry: [require.resolve('./polyfills'), paths.appIndexJs],
+ entry: {
+ main: [require.resolve('./polyfills'), paths.appIndexJs],
+ esmodule: paths.appIndexJs,
+ }
But there's no way to change babel-preset-env in the config, depending on the entry point.
If you duplicate your production webpack config, you can handle things pretty well, but that has the weakness of... well... duplicating your production webpack config. @neeharv has gotten a build working pretty well using this so I might let him describe it.
One thing worth pointing out is that we had to use the beta version of UglifyJSPlugin to get the ecma config property, otherwise ES6 code would break. So CRA would probably need to bump to whatever version of webpack includes this, once it goes stable.
This is where my thinking is at atm. If your webpack plugin targets beautiful new ES6 code with no polyfills and very little transpilation, but then something comes along and transpiles it to ES5. I've played around with unminified-webpack-plugin a bit and tried to get something similar working, but don't know webpack really well enough to ship this quickly. What it would need to do, though, is this:
.nomodule.js or something similartype="module" for index.js, nomodule for nomodule.js)This does feel like an achievable goal, and makes sense to be done as a webpack plugin. There are still questions around serviceworker, given that it reads from the manifest, but we haven't got that far yet.
So that's where we got to in a couple of hours hacking. I think this is a really cool idea and has the potential to dramatically cut down bundle sizes for modern browsers, so would love to see this progress!
@geelen great work!
This does feel like an achievable goal, and makes sense to be done as a webpack plugin.
Totally agree with this.
I guess we have to summon webpack gurus to find the best way to go.
cc @sokra @TheLarkInn
/cc @addyosmani
I recall seeing a tweet that this is horrible for performance.
Can you shed some light? Thanks!
@Timer, I don't know the exact tweet you're referencing, but I'm sure it was about using the module loading feature and letting the browser load your entire dependency graph rather than using a bundler.
The technique I describe in the article side-steps that performance issue by still depending on webpack to do the bundling.
Thanks for the ping! Just had a chat with @philipwalton. The pattern he suggested in his article is fine to adopt and we reviewed it before it was published. It focuses on including a bundled top-level script using <script type=module> instead of requiring a complete dependency graph to be loaded and parsed.
My performance concerns there have been that Chrome and other browsers currently haven't optimized the unbundled ESM use-case yet and we currently have lots of work to do bringing down IPC and parse/compile costs. Feel free to use the pattern in the article without any perf concerns from my side 馃憤
I'll be putting up a rough WIP PR on this soon, by turning the webpack config into a factory of sorts and calling the build function multiple times using a different target each time. It's a pretty hacky way right now, but it has the advantage of generating separate asset-manifest files for each target, making it easy to figure the right service-worker to serve up to the user.
A potential problem with doing this using a webpack plugin is that it'll emit new files and add them to the manifest, and then plugins like sw-precache that rely on the manifest will have es5 + es6 code in their static config.
Super excited about this, seeing a rough reduction of ~10% in the default bundle file size already for the ES6 build.
Chrome and other browsers currently haven't optimized the unbundled ESM use-case yet and we currently have lots of work to do bringing down IPC and parse/compile costs. Feel free to use the pattern in the article without any perf concerns from my side
@addyosmani thanks for the clarification!
Landed basic WIP PR in #3136, we need to figure a better way to do this. Would love to hear some suggestions!
I think it's a cool idea in theory but I don't see how it could progress unless Webpack gets 10x better at caching. We are already blamed for very slow builds; can't make them twice as slow.
I reckon you'd only need the legacy build on production builds and not development builds, so it would only affect the production build time, no? Does that make a difference?
Yes, production build time is the one people are struggling with.
https://github.com/facebookincubator/create-react-app/issues/2763
https://github.com/facebookincubator/create-react-app/issues/913
some people already complain about slow production builds. It would be nice if we can do this parallelly though.
I don't really see us increasing complexity to support this.
yea, maybe someone can build a package that simplifies this. 馃槈
...so this is dead? Has anyone built like a plugin or something? I would really love to have this feature for performance and debugging.
@MidnightDesign cra v2 uses browserslist
@Djelnar Does that imply that this should work now? How?