NativeScript / nativescript-dev-webpack

A package to help with webpacking NativeScript apps.
Apache License 2.0
97 stars 49 forks source link

Proposal: Use webpack-dev-server instead of watch mode #1027

Closed shiv19 closed 4 years ago

shiv19 commented 5 years ago

Current HMR in {N} 6 is taking quite a lot of time on larger projects. On the project I work on, it takes about 8 to 13 seconds for the webpack in watch mode to bundle the changes. The process of syncing to the device is quite fast. It's the bundling process that is slowing HMR down right now.

After reading up on how to optimize webpack bundling speeds I came across webpack-dev-server, and sure enough, it was blazing fast. This is because dev-server doesn't write the files to the file system. However, there is an optional parameter in the webpack config file with which you can tell it to write to the file system, even then this is way faster when compared to watch mode.

To put things into perspective, on the same project where I got bundling speed of 8 to 13 seconds with watch mode, I got 1 to 2 seconds of bundling speed with webpack dev server. And that's a really major improvement I would say.

I've demonstrated it in a project here git clone https://github.com/shiv19/nativescript-sdk-examples-js.git npm i npm run dev-server

notice how fast the bundling works with dev-server.

Adding this to the webpack.config.js's config object makes it so that the dev-server writes the changes to the file system

devServer: { // https://webpack.js.org/configuration/dev-server/#devserverwritetodisk-
    writeToDisk: true
}

Without Dev server https://drive.google.com/file/d/168E25V1J9UyimjxbOAV4KO-sm74wKB66/view?usp=sharing

With Dev server https://drive.google.com/file/d/1Vwb799OZw5STUEOkKu_GCqT2loFu91hT/view?usp=sharing

About webpack caching, I've tried using webpack caching, it messes up when you want to build for the other platform. Let's say you used webpack caching to build for Android, now when you build for iOS, android version of some plugins can end up in the ios bundle (this happened to me with nativescript-bluetooth plugin).

DimitarTachev commented 4 years ago

Hi @shiv19,

Thanks for the detailed proposal and the attached samples!

webpack-dev-server is a development server that provides live reloading for web browsers. It uses webpack-dev-middleware under the hood which provides fast in-memory access to the webpack assets.

webpack-dev-middleware is a development middleware for express.js web servers that allows serving of emitted files from Webpack without writing them to the disk.

For example, when a web browser requests the website files, an express server is serving them from the webpack-dev-middleware. When the developer updates the code, webpack-dev-server is refreshing the browser through a web socket (similar to the NativeScript live sync feature).

In other words, I'm not sure if we can get any benefits from the webpack-dev-server and webpack-dev-middleware.

Regarding your performance observations, the webpack-dev-server approach is faster in the attached application because it's running the webpack process with a single env flag - env.android.

In this way, it does not include the HMR plugin and does not generate source maps while when you execute tns run android, it enables env.android, env.hmr and env.sourceMap.

I've opened a PR for unifying the Webpack env in your sample repository and when the nativescript-dev-server and tns run android are using the same Webpack env, the performance results are equal.

Maybe we can get the Webpack compilation faster if we stop writing the output files to the platforms directory and start syncing them directly to the device (something similar to the webpack-dev-middleware but in the NativeScript CLI, not an express server) but that's a different proposal.

I hope you'll be able to take a look at the PR and update us back if I'm getting something wrong or you have some additional ideas.

shiv19 commented 4 years ago

@DimitarTachev thanks for the detailed explanation, that makes sense. I'll look at the PR and get back to you on Monday morning NZDT.

shiv19 commented 4 years ago

@DimitarTachev I confirm that after adding env hmr and sourceMap the compilation time is the same. I support your idea of > we stop writing the output files to the platforms directory and start syncing them directly to the device

do we want to close this issue at this point and start a new proposal?

DimitarTachev commented 4 years ago

@shiv19

Yeah, we can close this one and open the in-memory compilation proposal.

However, bear in mind that I'm not sure if it will be possible. The initial JS files should be written to the file system in order to be part of the generated apk/ipa/app. In other words, we could generate only the hot updates in memory but as far as I know, some of the iOS libs that we use to upload files during LiveSync require the files to be written to the file system.

We've planned to troubleshoot out Webpack performance by following the recommendations in the Webpack Build Performance article. Also, once Webpack 5.0 is officially released, we will plan to integrate its caching feature for additional performance improvements.