Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: Add ESM Import Maps support#759

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
stipsan wants to merge21 commits intodevelopit:master
base:master
Choose a base branch
Loading
fromeik-lib:import-map

Conversation

stipsan
Copy link
Contributor

@stipsanstipsan commentedNov 28, 2020
edited
Loading

This follows up on@developit'ssignal that ESM Import Maps is an interesting feature for microbundle.

TL;DR

This PR is about supporting theahead-of-time rewriting strategy that thedraft spec for ESM Import Maps talks about.

Background info, super detailed

AtFINN.no we run adiverse and distributed infra, with a constant stream of deployments that's only been interrupted when we moved data centersin the middle of the night.

To make it possible for each team to own their part of the page (for example the Recommendations team owns the feed of "Anbefalinger" on the front page) and deploy updates and changes anytime they want we developedPodium. Podium answers the question "how can we update a snippet of shared html everywhere at once without restricting the server stack" by composing pages over HTTP. The benefits of a distributed frontend system are many, but it came with a challenging cost: if two page fragments use the same dependency, how do we ensure it's only ever downloaded once?

We builtAsset Pipe to solve bundling for distributed systems. When a layout is starting up it figures out what assets each fragment needs, concatinates them, and sends them to our asset pipe server. When it's done bundling it'll create an optimized file for the js and another for the css, serving them on hashed URLs that are guaranteed to be unique:

<linkhref="https://static.finncdn.no/_podium-assets/caeb0dc97f9e53242615f218cdb35b6ddb426e69b2803bc2e91e22e8a84a29d5.css"media="all"type="text/css"rel="stylesheet"><scriptsrc="https://static.finncdn.no/_podium-assets/2a920eeee4c178549a1e1ca23869c55571750ddce280a16e4f8f07e0629539db.js"crossorigindefer></script>

The downside to this approach by "bundling as a service" is that bundling is a slow process and it's become a huge bottleneck. If a page fragment is deploying a new update it triggers bundling on each layout using it, causing a cascade of bundling processes starting up. We were also unhappy with the performance tradeoff by creating one hashed asset per layout that bundles everything. When a user moves from layout A to B ideally react shouldn't be redownloaded on layout B for example.

We decided to set out to replace Asset Pipe and explored different concepts to find the optimal trade-offs. It turns out that building a CDN asset service that is designed for ESM cache heuristics, HTTP2 and ESM Import Maps is a really good idea. We call this solutionEik.
It lets us publish assets to the CDN in a similar way as you would to npm, allowing assets to always be ready ahead-of-time for the page fragments that'll use them, with stable and immutable URLs. Making deployments as well as rollbacks fast as no bundling/rebundling is necessary.
The server part wasn't all we needed, we also had to create plugins for the bundlers people are using (rollup, esbuild, we're still waiting for webpack to supportlibraryTarget: "module" before we can add support there).

Many of our teams are used to the "bundling as a service" flow and don't have any bundler setup locally for their JSX or babel syntax. That's why we started looking at microbundle and saw it fit most of our needs, except that it didn't let us add custom rollup plugins andwe needed to make a fork.

How we're using Import Maps in production

AtFINN.no we've been testing this in production for a couple of months now, in combinationwith our ESM optimized CDN service. By using ESM Import Maps as our foundation we've been able to dedupe shared dependencies likereact in our distributed system.

Here's an example from our frontpage on what this looks like in production:

<scriptsrc="https://assets.finn.no/pkg/login-box/1.0.6/esm.js"type="module"crossorigindefer></script><scriptsrc="https://assets.finn.no/pkg/login-box/1.0.6/ie11.js"crossoriginnomoduledefer></script>

Browsers that support native ESM will loadesm.js which Import Maps react like this:

importefrom"https://assets.finn.no/npm/@pika/react/v16/index.js";importtfrom"https://assets.finn.no/npm/@pika/react-dom/v16/index.js";

The assets we import map to are aliased to latest major, similar to how unpkg.com works except we cache the 302 redirect for 20 minutes instead of 1 minute. This speeds things up considerably as the user browse around on our marketplace. We also use-f modern to generate theesm.js files to further reduce the amount of JS our users have to download. More info on the setupin the docs.

The performance results we've seen in the last couple of months in production are promising and encouraging. We believe that betting on the import map spec (over competing solutions like Webpack's Module Federation) is the way to go.

@changeset-bot
Copy link

changeset-botbot commentedNov 28, 2020
edited
Loading

🦋 Changeset detected

Latest commit:4e028e6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
microbundleMinor

Not sure what this means?Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@developit
Copy link
Owner

This looks pretty good! I'm wondering if it would make sense to have the--import-map option be a path to the JSON import map - would that match what you're using in other tools?

@stipsan
Copy link
ContributorAuthor

Hey@developit I've discussed your suggestion with@trygve-lie and@digitalsadhu.
It would indeed be a good match for our tooling.
Downloading ourEik import maps to a local file is something we want our@eik/cli client to be able to do anyway.
It's much easier to test native import mapping in the browser when it's as simple as:

res.send(`  <script type="importmap">${JSON.stringify(require('./import-map.json'))}  </script>`)

While production is a simple matter ofeik --download && microbundle --import-map ./eik/import-map.json for us 😄

@stipsan
Copy link
ContributorAuthor

@developit alright PR updated with your suggestion 😄

@stipsan
Copy link
ContributorAuthor

@developit oki ready for review, just had to fight node v12's "exports" behavior a little 😄

developit reacted with laugh emoji

@developit
Copy link
Owner

Approved! There's a discussion around whether Microbundle should be support anything other than the original "bundling for npm" use-case, so I'm going to hold off on merging this just yet.

stipsan reacted with hooray emoji

@developitdevelopit added the increased scopeIncreases project scope, or is out of scope. labelDec 18, 2020
@stipsan
Copy link
ContributorAuthor

@developit cool! I see the value in having that discussion. When a tool solves a particular problem well, it's always tempting to scale it up to solve a similar but not quite the same problem.
Maybe the use case "bundling for CDN" warrants a new library instead of scope creeping microbundle.
I don't know enough to form an opinion on it yet. But I must say that we haven't found an elegant setup when using microbundle outside npm. We often need to resort to--no-pkg-main, losing benefits like watch mode for multiple targets without resorting to spawn or lerna.

Is the discussion happening somewhere public?

developit reacted with thumbs up emoji

@developit
Copy link
Owner

developit commentedDec 18, 2020
edited
Loading

Heh - glad we are on the same page there. Yes, the discussion is happening in the#microbundle channel on thePreact slack. You can come commiserate with us on how much work it is to maintain things! :D

stipsan reacted with laugh emoji

@stipsan
Copy link
ContributorAuthor

@developit hahaha you got me at "commiserate" 😂

developit reacted with laugh emoji

@stipsan
Copy link
ContributorAuthor

Completely forgot about this 🙌 did we reach a consensus/conclusion on this@developit?

chicken-suop reacted with thumbs up emoji

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@developitdevelopitdevelopit approved these changes

Assignees
No one assigned
Labels
increased scopeIncreases project scope, or is out of scope.
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

2 participants
@stipsan@developit

[8]ページ先頭

©2009-2025 Movatter.jp