aurelia / framework

The Aurelia 1 framework entry point, bringing together all the required sub-modules of Aurelia.
MIT License
11.75k stars 623 forks source link

Putting Aurelia on a diet #692

Open jods4 opened 7 years ago

jods4 commented 7 years ago

There is a lot of awareness around "modern" web app sizes and their libs recently. I am assuming this is obvious so won't repeat all here (download times, parsing/startup time, mobiles, etc.). Some libraries make efforts to reduce size, for example jQuery has slimmed down by stopping supporting old browsers and removed deprecated apis. It also offers non-bundled sources so that you can import only the modules you actually use.

Some of Aurelia's competitors take pride in being very small: React is 45K gzipped, Vue.js 17K and Inferno only a tiny 9K! Of course, the comparaison is never completely fair because it depends on supported targets and the feature set (for example none of the numbers above include a router). But it gives an idea what to aim for.

Aurelia is not lightweight. Here's an analysis of a basic, empty app. The only dependency in project.json is aurelia-bootstrapper. It was built with Webpack 2.2 and minified with default settings. Spoiler: the whole thing is 85Ko gzipped, almost 10 times Inferno.

Here's a picture of the whole thing, the treemap is proportional to gzipped size: aurelia-size

And for reference, some modules:

Module Raw Minified Gzipped
aurelia-binding 166K 91K 20K
aurelia-templating 146K 69K 18K
aurelia-templating-resources 75K 37K 16K
aurelia-router 54K 26K 7K
aurelia-hot-module-reload 40K 16K 5K
aurelia-polyfills 22K 10K 4K
Full bundle 700K 343K 85K

There is essentially two ways to improve: (1) enable people to only include what they actually use (granular modules and/or tree shaking). This is already discussed in other issues. (2) reduce the size of the code.

I noticed a few low-hanging fruits:

There is definitely potential for improvement in the code but unless obvious wasted or duplicated code is found it will be made of many small wins. :( binding, templating and templating-resources are really the lion's share in the core packages.

jods4 commented 7 years ago

I am a little bit surprised: if you use the BabiliPlugin directly I would expect it to work even without the --optimize-minimize flag, which I believe adds the Uglify plugin for you.

Robula commented 7 years ago

I am using it like so;

    plugins: [
        new AureliaPlugin({
            aureliaConfig: ["basic"],
            features: { ie: false, svg: false, unparser: false, polyfills: "es2015" }
        }),
        new BabiliPlugin()
    ]

My deps are;

    "dependencies": {
        "aurelia-bootstrapper": "^2.1.1"
    },
    "devDependencies": {
        "aurelia-webpack-plugin": "^2.0.0-rc.1",
        "babili": "^0.0.12",
        "babili-webpack-plugin": "^0.0.11",
        "compression-webpack-plugin": "^0.3.2",
        "html-loader": "^0.4.5",
        "html-webpack-plugin": "^2.28.0",
        "source-map-loader": "^0.2.0",
        "ts-loader": "^2.0.3",
        "typescript": "^2.2.2",
        "webpack": "^2.3.2",
        "webpack-dev-server": "^2.4.2"
    }

Calling webpack produces 245K. Calling webpack --optimize-minimize produces 233K.

jods4 commented 7 years ago

You have latest Aurelia libs? All those flags were added very recently. I use my "small ES6" demo to test this and I can definitely see the difference.

Robula commented 7 years ago

I have just deleted by node_modules and npm-cache folders and did a fresh npm install from the dependencies listed above and I am seeing the same result.

D:\Dev\Repo\Aurelia-AutoComplete>webpack
ts-loader: Using typescript@2.2.2 and D:\Dev\Repo\Aurelia-AutoComplete\tsconfig.json
Hash: 6e18e99bfe895f7fb6c2
Version: webpack 2.3.2
Time: 25288ms
        Asset    Size  Chunks                    Chunk Names
app.bundle.js  250 kB       0  [emitted]  [big]  app
D:\Dev\Repo\Aurelia-AutoComplete>webpack --optimize-minimize
ts-loader: Using typescript@2.2.2 and D:\Dev\Repo\Aurelia-AutoComplete\tsconfig.json
Hash: 6e18e99bfe895f7fb6c2
Version: webpack 2.3.2
Time: 30332ms
        Asset    Size  Chunks             Chunk Names
app.bundle.js  238 kB       0  [emitted]  app

I'm personally not worried about it as I now know to pass --optimize-minimize if building for production. Also this is probably either a webpack@2 or babili-webpack-plugin specific issue, not Aurelia.

jods4 commented 7 years ago

@Robula I'm not sure what is going with your project.

I did an experiment with my ES6 Small Build demo. Using exactly what is committed, yarn install followed by yarn run webpack produces a bundle that is 277,934 bytes.

If I comment out the feature line then the resulting bundle is 309,674 bytes.

So there's approx. a 30K win by removing unused features. Looking at the bundle contents I can see the polyfills being there or missing.

nashwaan commented 7 years ago

@jods4

How did you create this treemap of the project?

image

zewa666 commented 7 years ago

@nashwaan https://github.com/th0r/webpack-bundle-analyzer

jods4 commented 7 years ago

I upgraded everything to Webpack 3 today.

Without any change, I was happy to see it provided a 13% minified size reduction. 😄

Then I tried the new scope hoisting, aka ModuleConcatenationPlugin, aka rollup. And that saved 194 bytes. Yeah, I know...

Don't get me wrong, scope hoisting is great and provides faster load times, and smaller sizes if you use tons of small modules.

There are a couple reasons why it isn't efficient on this application:

Your mileage may vary. In a large application, the more files and the more libraries you use the better the results.

Anyway, new build is 242'310 bytes minified, 64Kb gzipped.

jods4 commented 6 years ago

Note from Webpack 4 upgrade, the same build as above but using built-in mode: "production" of Webpack 4 is 237'314 bytes. Less than before, nothing spectacular.

I expect some larger wins if we start to use the new side-effects: false metadata in Aurelia packages where we can.

jpsala commented 6 years ago

Yessss, thanks you

https://media.giphy.com/media/axu6dFuca4HKM/giphy.gif

EisenbergEffect commented 6 years ago

In addition to the original plans, we're also currently experimenting with a compile-time transform version of Aurelia that would obviate the need for huge parts of the framework, move certain runtime components into the build process and allow dropping all parts of the framework unused by the app. We're early on in the experimental process, but you can watch via the experiment repo.