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

Encoded inline bundles #3726

Merged
merged 19 commits into from
Nov 14, 2019
Merged

Encoded inline bundles #3726

merged 19 commits into from
Nov 14, 2019

Conversation

wbinnssmith
Copy link
Contributor

@wbinnssmith wbinnssmith commented Nov 1, 2019

Resolves #3718.

This implements the ability to inline the content of one bundle into another by using protocol-style imports in the form of data-url:./img.png to receive a data url or bundle-text:./worker.js to receive the literal text of the compiled bundle content.

This is accomplished by adding transformer-inline, which sets isInline to true on assets, attaching the requested pipeline name to assets and bundles, and adding an optimizer to transform bundle contents into data urls. References to the inline bundle are left behind in the form of bundle ids (this may change with css), and the packaged inline bundles are then replaced during packaging by invoking the inline packaging api.

For data urls, the mimetype is automatically determined based on the bundle filepath, and the content is encoded either as text for non-binary content, or as base64 for binary content (content with a 0x00 byte present).

Question: Is there a more robust heuristic for determining binary content than checking for the presence of a 0x00 byte?

Remaining tasks:

  • Add support for url dependencies
  • Add support in the css packager
  • Adjust source maps to reflect inline content

Test Plan: Added integration tests.

@wbinnssmith
Copy link
Contributor Author

wbinnssmith commented Nov 1, 2019

Re: detecting binary files, https://www.npmjs.com/package/isbinaryfile has an extra step that counts characters it considers "weird". We could use that module here instead.

@parcel-benchmark
Copy link

parcel-benchmark commented Nov 1, 2019

Benchmark Results

packages/benchmarks/kitchen-sink 🚨

Timings

Description Time Difference
Cold FAILED -0.00ms
Cached FAILED -0.00ms

Cold Bundles

No bundles found, this is probably a failed build...

Cached Bundles

No bundles found, this is probably a failed build...

packages/benchmarks/react-hn ✅

Timings

Description Time Difference
Cold 13.14s -175.00ms
Cached 11.95s +1.19s ⚠️

Cold Bundles

Bundle Size Difference Time Difference
dist/main/index.js 34.53kb +0.00b 1.99s -138.00ms 🚀
dist/module/index.js 34.33kb +0.00b 1.99s -138.00ms 🚀

Cached Bundles

No bundle changes detected.

packages/benchmarks/ak-editor ✅

Timings

Description Time Difference
Cold 3.31m +8.19s
Cached 10.23s +550.00ms ⚠️

Cold Bundles

Bundle Size Difference Time Difference
dist/index.js 2.31mb -312.00b 🚀 1.96m +7.15s ⚠️
dist/popup.a9bec4e0.js 284.70kb +0.00b 2.00m +7.51s ⚠️
dist/popup.37645d0d.js 44.40kb +0.00b 39.44s -2.43s 🚀
dist/popup.e57e7ab5.js 43.88kb +0.00b 41.70s +2.12s ⚠️
dist/js.adf5baf7.js 16.54kb +0.00b 1.96m +7.16s ⚠️
dist/card.f99e1597.js 5.89kb +0.00b 16.20s -1.60s 🚀
dist/png-chunks-extract.3d8d8594.js 3.33kb +0.00b 1.96m +7.16s ⚠️
dist/card.9520f336.js 1.80kb +0.00b 16.20s -1.60s 🚀
dist/workerHasher.64914391.js 1.48kb +0.00b 1.03m +13.32s ⚠️
dist/media-viewer-analytics-error-boundary.dd752a9e.js 777.00b +0.00b 16.19s -1.60s 🚀
dist/simpleHasher.c5e45ebc.js 446.00b +0.00b 1.03m +13.32s ⚠️
dist/dropzone.976debcc.js 177.00b +1.00b ⚠️ 1.96m +1.26m ⚠️
dist/clipboard.976debcc.js 177.00b +1.00b ⚠️ 42.52s +241.00ms
dist/browser.976debcc.js 177.00b +1.00b ⚠️ 1.03m +19.55s ⚠️
dist/editorView.976debcc.js 177.00b -1.00b 🚀 41.70s -20.70s 🚀
dist/media-card-analytics-error-boundary.976debcc.js 176.00b -5.00b 🚀 43.26s -1.12m 🚀
dist/16.976debcc.js 174.00b -5.00b 🚀 42.52s -881.00ms
dist/card.aae6ebb9.js 62.00b +0.00b 16.19s -1.60s 🚀

Cached Bundles

Bundle Size Difference Time Difference
dist/index.js 2.32mb -312.00b 🚀 384.00ms +33.00ms ⚠️
dist/pdfRenderer.0c70848e.js 1.14mb +0.00b 263.00ms +17.00ms ⚠️
dist/popup.a9bec4e0.js 284.70kb +0.00b 195.00ms +11.00ms ⚠️
dist/media-viewer.12bd9010.js 86.76kb +0.00b 177.00ms +9.00ms ⚠️
dist/card.80c210d3.js 76.35kb +0.00b 177.00ms +9.00ms ⚠️
dist/DatePicker.6844209a.js 27.57kb +0.00b 129.00ms -9.00ms 🚀
dist/EmojiPickerComponent.bb15ebef.js 26.66kb +0.00b 129.00ms -9.00ms 🚀
dist/EmojiTypeAheadComponent.1c09c30d.js 10.44kb +0.00b 128.00ms -10.00ms 🚀
dist/index.css 3.38kb +0.00b 106.00ms -13.00ms 🚀
dist/feedback.4dda4a59.js 2.93kb +0.00b 130.00ms -9.00ms 🚀
dist/EmojiUploadComponent.0460cc59.js 2.91kb +0.00b 128.00ms -10.00ms 🚀
dist/16.dcacbe5c.js 1.69kb +0.00b 140.00ms -9.00ms 🚀
dist/date.cfe6153f.js 1.63kb +0.00b 137.00ms -10.00ms 🚀
dist/16.de3f3184.js 1.62kb +0.00b 143.00ms -9.00ms 🚀
dist/images.c60a97a9.js 1.57kb +0.00b 136.00ms -9.00ms 🚀
dist/workerHasher.30e330ec.js 1.48kb +0.00b 128.00ms -9.00ms 🚀
dist/workerHasher.854262ce.js 1.48kb +0.00b 127.00ms -10.00ms 🚀
dist/workerHasher.64914391.js 1.48kb +0.00b 126.00ms -10.00ms 🚀
dist/status.e3ed4764.js 1.35kb +0.00b 133.00ms -9.00ms 🚀
dist/list-number.dbe744df.js 1.35kb +0.00b 135.00ms -9.00ms 🚀
dist/16.8f0e8fe1.js 1.29kb +0.00b 143.00ms -9.00ms 🚀
dist/16.43b62c01.js 1.29kb +0.00b 142.00ms -9.00ms 🚀
dist/code.092e0137.js 1.28kb +0.00b 138.00ms -9.00ms 🚀
dist/16.b17a4d30.js 1.27kb +0.00b 139.00ms -9.00ms 🚀
dist/16.51bbc68e.js 1.23kb +0.00b 139.00ms -9.00ms 🚀
dist/link.6fa27bb2.js 1.20kb +0.00b 135.00ms -9.00ms 🚀
dist/heading6.3996fe48.js 1.19kb +0.00b 130.00ms -9.00ms 🚀
dist/16.385d3ff5.js 1.19kb +0.00b 140.00ms -9.00ms 🚀
dist/heading3.9fea5413.js 1.18kb +0.00b 131.00ms -10.00ms 🚀
dist/16.b3ce4050.js 1.16kb +0.00b 142.00ms -10.00ms 🚀
dist/16.e37bbe6b.js 1.15kb +0.00b 140.00ms -8.00ms 🚀
dist/16.f7fe274a.js 1.14kb +0.00b 138.00ms -9.00ms 🚀
dist/emoji.c4bc5355.js 1.12kb +0.00b 136.00ms -9.00ms 🚀
dist/16.ac2ff83f.js 1.10kb +0.00b 140.00ms -9.00ms 🚀
dist/16.4c652b29.js 1.10kb +0.00b 141.00ms -10.00ms 🚀
dist/16.24165259.js 1.09kb +0.00b 142.00ms -10.00ms 🚀
dist/16.97c5bdf9.js 1.09kb +0.00b 140.00ms -9.00ms 🚀
dist/16.a79db876.js 1.09kb +0.00b 143.00ms -9.00ms 🚀
dist/heading5.2f045997.js 1.06kb +0.00b 131.00ms -9.00ms 🚀
dist/16.3e36da0b.js 1.01kb +0.00b 140.00ms -8.00ms 🚀
dist/heading2.2194210a.js 1.00kb +0.00b 132.00ms -9.00ms 🚀
dist/mention.9fdad24e.js 981.00b +0.00b 134.00ms -9.00ms 🚀
dist/fallback.305c8864.js 980.00b +0.00b 132.00ms -9.00ms 🚀
dist/heading4.63d1ca06.js 976.00b +0.00b 131.00ms -9.00ms 🚀
dist/layout.6f66c2da.js 962.00b +0.00b 136.00ms -9.00ms 🚀
dist/divider.160f3108.js 940.00b +0.00b 137.00ms -8.00ms 🚀
dist/quote.88bfdca4.js 936.00b +0.00b 133.00ms -9.00ms 🚀
dist/action.146450ba.js 919.00b +0.00b 138.00ms -9.00ms 🚀
dist/decision.06254b93.js 898.00b +0.00b 137.00ms -9.00ms 🚀
dist/panel-warning.59c8ef3f.js 891.00b +0.00b 134.00ms -8.00ms 🚀
dist/list.4f623de3.js 870.00b +0.00b 135.00ms -8.00ms 🚀
dist/heading1.65fb8482.js 864.00b +0.00b 132.00ms -9.00ms 🚀
dist/panel-error.c2479698.js 791.00b +0.00b 134.00ms -9.00ms 🚀
dist/panel.23cd7224.js 788.00b +0.00b 134.00ms -7.00ms 🚀
dist/table.4ace5843.js 780.00b +0.00b 133.00ms -9.00ms 🚀
dist/panel-success.6a7b97d7.js 728.00b +0.00b 134.00ms -8.00ms 🚀
dist/panel-note.5ff85bdc.js 727.00b +0.00b 135.00ms -7.00ms 🚀
dist/simpleHasher.f8edc084.js 446.00b +0.00b 127.00ms -10.00ms 🚀
dist/simpleHasher.884d4eb6.js 446.00b +0.00b 127.00ms -10.00ms 🚀
dist/simpleHasher.c5e45ebc.js 446.00b +0.00b 125.00ms -11.00ms 🚀
dist/esm.976debcc.js 176.00b +2.00b ⚠️ 165.00ms +4.00ms
dist/media-card-analytics-error-boundary.976debcc.js 176.00b +2.00b ⚠️ 161.00ms +1.00ms
dist/dropzone.976debcc.js 176.00b +2.00b ⚠️ 156.00ms +1.00ms
dist/clipboard.976debcc.js 176.00b +2.00b ⚠️ 155.00ms -0.00ms
dist/browser.976debcc.js 176.00b +2.00b ⚠️ 155.00ms +1.00ms
dist/16.976debcc.js 176.00b +2.00b ⚠️ 139.00ms -8.00ms 🚀
dist/editorView.976debcc.js 176.00b +2.00b ⚠️ 125.00ms -10.00ms 🚀

Click here to view a detailed benchmark overview.

@wbinnssmith wbinnssmith force-pushed the wbinnssmith/inline-bundle-urls branch 8 times, most recently from 2a8a310 to 4e7fa48 Compare November 4, 2019 21:43
@wbinnssmith wbinnssmith marked this pull request as ready for review November 4, 2019 21:44
@wbinnssmith wbinnssmith force-pushed the wbinnssmith/inline-bundle-urls branch 9 times, most recently from 2f146d0 to 456afb9 Compare November 5, 2019 23:07
if (dependency.moduleSpecifier.includes(':')) {
[pipeline, filePath] = dependency.moduleSpecifier.split(':');
let transformsWithPipelines = {};
for (let key of Object.keys(this.config.transforms)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also include optimizers here? What if you had a named pipeline that only existed in the optimizer config?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Think we should be using the config matching method or just extract the pipelines ourselves here and match against them?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we could extract the named pipelines once and cache them? Maybe in the ParcelConfig class?

@@ -0,0 +1,9 @@
// @flow strict-local

export function escapeJSStringLiteral(str: string): string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just use JSON.stringify?

: packagedBundle.contents
).toString();

let inlineType = nullthrows(entryBundle.getMainEntry()).meta.inlineType;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we define what inlineType values are allowed? I'm not sure it should be enforced in this util in case new ones need to be defined by plugins.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not really enforced. inlineType isn't a formal concept in core and is just something that transformers and packagers agree on.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's enforced by the line below asserting the values...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function isn't run in core though, it's run in packagers. Perhaps this util shouldn't live in core/utils?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah true, but the util is still kinda “shared” code that shouldn’t make assumptions if it’s meant to be informal.

@wbinnssmith wbinnssmith merged commit bf85cd5 into v2 Nov 14, 2019
@devongovett devongovett deleted the wbinnssmith/inline-bundle-urls branch November 14, 2019 18:06
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.

RFC: Encoded Inline Bundles
3 participants