-
Notifications
You must be signed in to change notification settings - Fork 119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add webpack demo app to show how to tree shake out only the methods in use #490
Conversation
@@ -17,9 +17,9 @@ | |||
"scripts": { | |||
"prepare": "npm run build", | |||
"build": "npm run build:node && npm run build:umd && npm run build:esm", | |||
"build:esm": "tsc -p ./tsconfig.json --module es2015 --outDir ./dist/esm --declaration", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its not necessary to call out the location of the tsconfig.json
file explicitly.
the compiler searches for the tsconfig.json file starting in the current directory and continuing up the parent directory chain. - (reference)
Codecov Report
@@ Coverage Diff @@
## master #490 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 95 95
Lines 1214 1214
Branches 225 225
=====================================
Hits 1214 1214 Continue to review full report at Codecov.
|
@jgravois I would like to review this but give me a few days. |
Ditto. I'd like to try this out in an app I have that uses the ExB build. I also wonder if we can do this in Hub.js first, since the stakes aren't as high there. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jgravois it looks like the --target es2017
flag does what I thought it did. The target
param tells typescript output only code compliant with the specified target. This means that all ES2015 features like class
are not compiled since they are assumed to be available under ES2017. This is why we see such a good reduction in size in this PR, TypeScript simply doesn't have to compile as much code. This also helps tree shaking algorithms figure out what code they can successfully drop since those algorithms don't have to parse through compiled code.
BUT this also comes at a cost which I think is too high. This will break in all browsers that don't support ES 2017. Which is pretty older versions of Chrome, Firefox, Safari, Edge and most importantly IE 11. This would be broken in these browsers until developers tell Babel (or maybe TypeScript) to compile code that is loaded from arcgis-rest-*
down to ES5, since the default behavior for both Babel and TS is to not compile any code that comes from node_modules
.
Since arcgis-rest-js
is used in a TON of applications (ArcGIS for Developers included) I don't think we can make this change without at least a major version, but then people would still continue to use 1.x for IE 11 support.
Finally, our modules are REALLY small compared to what most developers will be using in a larger application and this change will only affect developers who are bundling with a really modern bundle like WebPack or Rollup and then most of the savings from this will shrink once that 4.76KiB that saved gets turned into ~1KiB or less after GZip
thanks @patrickarlt. i did some more snooping this morning and it appears that Stencil.js compiles the TypeScript for web components into both |
@jgravois I suppose we could create 2 builds and do something like what https://philipwalton.com/articles/deploying-es2015-code-in-production-today/ proposes allowing users to use something like this: <!-- Browsers with ES module support load this file. -->
<script type="module" src="main.mjs"></script>
<!-- Older browsers load this file (and module-supporting -->
<!-- browsers know *not* to load this file). -->
<script nomodule src="main.es5.js"></script> This means we would essentially end up with the following builds:
The main issue I could see here would be having to make 2 builds from the same code so that: import {request} from "@esri/arcgis-rest-request"; in the ES5 build could seamlessly become: import {request} from "@esri/arcgis-rest-request/modern"; In the ES2015/ES2017 build without having to make a bunch of code changes. Overall though this still doesn't seem worth it to be for the size savings. |
thanks @patrickarlt.
for some of the packages here, you're probably right, but in |
@jgravois I guess for the hub.js case it MIGHT make a difference. But I still think there isn't really a whole lot to tree shake out. You can really cant shake anything out of You would probably get more luck out of
I just think the initial sizes are too small to really make meaningful gains. Is shaving 1kb or even 2kb off of hub.js worth the high cost in terms of changing our existing build process? I can't help but feel like this is a REALLY premature optimization for optimizations sake. The entirety of
With Don't get me wrong I love saving on size where we can I just don't think we should have 1-2Kb off some peoples builds is worth dropping a lot of compatibility. If we still want to do this we can but I think we need to do a clean break at v2 to do it and even then we will still need to maintain v1 for people who need to extra compat with older browsers. |
i appreciate you humoring me @patrickarlt. imagine this scenario: in a Stencil.js web component, i want to: import { followInitiative, unfollowInitiative } from "@esri/hub-initiatives"; the dependency graph for these methods includes:
with
it may be, but my inclination as a developer, and i've seen customers doing the same thing, is to ignore that the function already exists in a higher order package and just rewrite it myself in my application using only that works of course, but when users do this they miss out on a lot of the good work we've done. as you said, the file sizes aren't that big. but listing all the modules below in my package.json when i only want to import two methods just feels like i'm including a lot more than i need. especially when Stencil is configured by default to create different bundles to serve up to ES2017 browsers and a bigger package to deliver to IE11 automatically.
to be honest, i had no idea something like this would be necessary. i just (optimistically) hoped we could add another target and surface it as yet another available compiled source in the
if that's the crux of the issue, i understand. |
tl;dr
@jgravois lets publish a new version of each module with @jgravois ok I'll bite lets figure out how we can make this work. I forgot about the module fields in package.json. So on order to not break backward compat lets do this. Update
{
"build:esm-modern": "tsc --module es2015 --target ES2015 --outDir ./dist/esm-2015 --declaration",
"build:esm": "tsc --module es2015 --outDir ./dist/esm --declaration",
"build:node": "tsc --module commonjs --outDir ./dist/node",
"build:umd": "rollup -c ../../umd-base-profile.js && rollup -c ../../umd-production-profile.js"
} Then we can declare our new build in {
"main": "dist/node/index.js",
"unpkg": "dist/umd/auth.umd.js",
"module": "dist/esm/index.js",
"module:es2015": "dist/esm-2015/index.js",
"js:next": "dist/esm/index.js",
"types": "dist/esm/index.d.ts",
} I'm pretty sure that Stencil should still tree-shake if we target ES2015. It is worth testing since far more people will be able to adopt a 2015 standard then a 2017 one. Also we aren't writing any I also think the approach of adding a new
My interpretation of this is that we should still ship ES5 in the However in doing all my research on this I found a few things:
|
demos/tree-shaking/src/index.js
Outdated
let element = document.createElement('div'); | ||
document.body.appendChild(element); | ||
|
||
searchItems() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jgravois fix this and
I'll write something up in https://github.com/Esri/arcgis-rest-js/tree/master/notes or the wiki about treeshaking later and summarize all the research I did on this.
AFFECTS PACKAGES: @esri/arcgis-rest-webpack-demo ISSUES CLOSED: #424
@tomwayson TL:DR; adding |
I really appreciate all the thought you both have put into this and am looking forward to the writeup! |
i had a chat with @adamdbradley today 🎩 and he clued me in that consumers will have more luck tree-shaking our ES modules if TypeScript targets something newer than
es5
during compilation.i don't see a downside to this change because i'd expect those consumers to understand that they have to bring their own transpiler to the party anyway.
instead of
AFFECTS PACKAGES:
@esri/arcgis-rest-webpack-demo
ISSUES CLOSED: #424