perf: Use named Parser import, to allow bundlers to create direct function references #535
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Currently YouTube.js uses a default export to export the Parser functions and the imports that default export, instead of the namespace export/import. Why is that a problem? Because namespace imports are special, the object they give you is special and known as a "module namespace object" (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import#module_namespace_object), which gets treated specially by bundlers, but because we are exporting said object with
default
we are telling the bundler we want it to be treated as a normal object instead. The result is larger bundles and potentially slower code as you are calling functions on an object, instead of calling the function directly.These changes have a very minimal impact on the bundles provided by YouTube.js because of an esbuild limitation (it doesn't handle re-exported namespaces well, see: evanw/esbuild#1420) but for anyone using deno, ES modules on node or the web export, will benefit from it, FreeTube for example saves
4337
bytes. This will also help anyone importing theParser
from YouTube.js and using it in their own code, as they'll get the direct function referencing benefits too.YouTube.js bundles size changes:
browser.js
-66
bytesbrowser.js.map
-50
bytesbrowser.min.js
-41
bytesbrowser.min.js.map
-85
bytesnode.cjs
-66
bytesnode.cjs.map
-52
bytesSo what exactly happens in FreeTube that it shaves off
4337
bytes. The screenshots below were taken with terser-webpack-plugin, patched to set terser's deprecated beautify option to true, the size measurements were taken without that modification. You may want to click on the screenshots to open them in a new tab, so that you can see them bigger.As we can see on this screenshot, instead of parseResponse being referenced/called directly, it is called on an object
PD
.If we look at what
PD
is, it's just a variable assignment so a bit boring, bute
is more interesting.Looks like
e
is an object containing named references referencing the actual parser functions. That's not what we want, but is what is caused by the default export and the use of it, we told the bundler that we don't care abou the module namespace object's special status, instead we want to use it as a normal object, so the bundler complies.So how does the situation look afterwards? Well that object disappeared from the output and the parseResponse function is now directly referenced/called, in this case
_E
.While that might not seem like a big change, the parser function are used in a lot of places in YouTube.js (just look at how many files I had to modify for this change), so that smalll change adds up quickly.