Skip to content
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

[performance] use JSON.parse(jsonSource) for JSON modules #9349

Merged
merged 2 commits into from Jul 2, 2019

Conversation

gfx
Copy link
Contributor

@gfx gfx commented Jul 2, 2019

Use JSON.parse(jsonSource) for JSON modules instead of object literals.

This is an implementation of the idea that comes from https://v8.dev/blog/cost-of-javascript-2019

As long as the JSON string is only evaluated once, the JSON.parse approach is much faster compared to the JavaScript object literal, especially for cold loads.

The article is written by the V8 team, but it should be true for all the JavaScript engines because JSON is much simpler than JavaScript.

NOTE: I didn't add an option to enable/disable this feature because users can easily use json-loader that converts JSON to JavaScript.

What kind of change does this PR introduce?

A performance optimization.

Did you add tests for your changes?

No. This PR does not change the behavior, but I've tested it on my production code that boosts ~20% of "loading" time on Chrome 75 in my bundle.js that includes over 1MiB of JSON objects.

Does this PR introduce a breaking change?

No.

What needs to be documented once your changes are merged?

No. It's just an implementation detail.


FYI you can try the implementation without patching webpack:

// optimized-json-loader.js
"use strict";

module.exports = function loadJsonModule(source) {
  if (typeof source !== "string") {
    throw new Error("Unexpected source type: " + typeof source);
  }
  const object = JSON.parse(source);
  const jsonSource = JSON.stringify(object);

  // cf. https://v8.dev/blog/cost-of-javascript-2019
  // > As long as the JSON string is only evaluated once, the JSON.parse approach is
  // > much faster compared to the JavaScript object literal, especially for cold loads.
  return `module.exports = JSON.parse(${JSON.stringify(jsonSource)});`;
};
// in webpack.config.js
const config = {
  // ...
  module: {
    rules: [
      {
        test: /\.json$/,
        type: "javascript/auto",
        use: {
          loader: path.resolve(__dirname, "./optimized-json-loader.js"),
        },
      },
    ],
   // ...
 }
};

(added on 2019/07/09)

To disable this feature in order to, for example, measure the performance, use the good old json-loader module:

const config = {
  // ...
  module: {
    rules: [
      {
        test: /\.json$/,
        type: "javascript/auto",
        use: {
          loader: "json-loader",
        },
      },
    ],
   // ...
 }
};

https://v8.dev/blog/cost-of-javascript-2019
> As long as the JSON string is only evaluated once, the JSON.parse approach is much faster compared to the JavaScript object literal, especially for cold loads.
@webpack-bot
Copy link
Contributor

For maintainers only:

  • This need to be documented (issue in webpack/webpack.js.org will be filed when merged)

@webpack-bot
Copy link
Contributor

Thank you for your pull request! The most important CI builds succeeded, we’ll review the pull request soon.

@gfx gfx changed the title use JSON.parse(jsonSource) for JSON modules [performance] use JSON.parse(jsonSource) for JSON modules Jul 2, 2019
@sokra sokra closed this Jul 2, 2019
@sokra sokra reopened this Jul 2, 2019
@sokra sokra merged commit 6dbae4b into webpack:master Jul 2, 2019
@sokra
Copy link
Member

sokra commented Jul 2, 2019

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants