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

Allow to specify resolve.alias or virtual module based on entry #16685

Closed
4 tasks done
Et7f3 opened this issue May 15, 2024 · 7 comments
Closed
4 tasks done

Allow to specify resolve.alias or virtual module based on entry #16685

Et7f3 opened this issue May 15, 2024 · 7 comments

Comments

@Et7f3
Copy link

Et7f3 commented May 15, 2024

Description

I have:

graph TD;

entry_admin --> page_admin.html
page_admin.html --> main_admin.jsx
main_admin.jsx --> router_admin.jsx
router_admin.jsx --> layout_admin.jsx
layout_admin.jsx --> navbar_admin.jsx
layout_admin.jsx --> footer.jsx

entry_user --> page_user.html
page_user.html --> main_user.jsx
main_user.jsx --> router_user.jsx
router_user.jsx --> layout_user.jsx
layout_user.jsx --> navbar_user.jsx
layout_user.jsx --> footer.jsx

In this setup it create many file but only two are really differents: navbar and router. I saw alias or virtual module could help me have:

graph TD;

entry_admin --> page.html
entry_user --> page.html
page.html --> main.jsx
main.jsx --> router_admin.jsx
main.jsx --> router_user.jsx
router_admin.jsx --> layout_admin["layout.jsx (from entry_admin)"]
router_user.jsx --> layout_user["layout.jsx (from entry_user)"]
layout_admin --> navbar_admin.jsx
layout_user --> navbar_user.jsx
layout_admin --> footer.jsx
layout_user --> footer.jsx

I replace resolve.alias based on an env var (but it cause to have two build command).

Suggested solution

Allow to put in entry section resolve.alias and other options that can be customized depending on entry.

Alternative

Pass top-level entry/dependencies path in custom resolver so we can implement this function user land.
create an overlay mechanism like nix: https://nixos.org/manual/nixpkgs/stable/#sec-overlays-alternatives

Additional context

No response

Validations

@sapphi-red
Copy link
Member

I guess you can configure it like:

import { defineConfig } from 'vite'

export default defineConfig({
  resolve: {
    '@/router': IS_ADMIN ? 'router_admin' : 'router_user',
    '@/navbar': IS_ADMIN ? 'navbar_admin' : 'navbar_user',
  },
  build: {
    rollupOptions: {
      input: IS_ADMIN ? 'admin' : 'user',
    },
  },
})

@Et7f3
Copy link
Author

Et7f3 commented May 17, 2024

I replace resolve.alias based on an env var (but it cause to have two build command).

I have a similar setup (the IS_ADMIN is on the whole resolve object):

  resolve: IS_ADMIN ? {
    '@/router': 'router_admin',
    '@/navbar': 'navbar_admin',
  } : {
    '@/router': 'router_user',
    '@/navbar': 'navbar_user',
  },

I just asked for a leaner way because if handled by vite it could split my bundle in three automatically without thinking about it:

common (main + router + footer), bundle_admin (router_admin + navbar_admin) and bundle_user (router_user + navbar_user)
index_user.html load common and bundler_user
index_admin.html load common and bundle_admin

@sapphi-red
Copy link
Member

Ah, I missed that sentence.

if handled by vite it could split my bundle in three automatically without thinking about it:

Do you mean you want to share chunks between admin and user? That won't be possible with your suggested solution.
For that you can load a file dynamically depending on a variable I guess.

graph TD;

entry_admin --> page_admin.html
page_admin.html --> main.jsx
main.jsx --> router_admin.jsx
router_admin.jsx --> layout.jsx
layout.jsx --> navbar_admin.jsx
layout.jsx --> footer.jsx

entry_user --> page_user.html
page_user.html --> main.jsx
main.jsx --> router_user.jsx
router_user.jsx --> layout.jsx
layout.jsx --> navbar_user.jsx
<!-- add in page_admin.html -->
<script>window.type = 'admin'</script>
<!-- add in page_user.html -->
<script>window.type = 'admin'</script>
// main.jsx
const loadRouter = () => {
  switch (window.type) {
    case 'user': return import('./router_admin.jsx')
    case 'admin': return import('./router_admin.jsx')
  }
  throw new Error('Unknown type')
}

;(async () => {
  const router = await loadRouter()

 // do something
})()

@Et7f3
Copy link
Author

Et7f3 commented May 17, 2024

(your did copy paste typo)

Thanks for the example it can improve my situations. So I have to write this code snippet for each selection ? so for my graph it will result in 5 chunks ? Maybe I could do a super user.jsx that load all user specific file and admin.jsx so I only have three.

Do you mean you want to share chunks between admin and user?

I just thought it was optimal to have three chunks. If there exist a solution with two chunk I can take this.

If I have two entry point rollup is called only one time with multiple input ? because if called twice we could just change the given file when launching it.

@sapphi-red
Copy link
Member

So I have to write this code snippet for each selection ? ... Maybe I could do a super user.jsx that load all user specific file

Yes, unless you could make a plugin that transforms your code. Or as you said, it'll work if you organize the dependency graph using dependency injection or something.

graph TD;

entry_admin --> page_admin.html
page_admin.html --> main.jsx
main.jsx -.-> admin.jsx
admin.jsx --> router_admin.jsx
admin.jsx --> navbar_admin.jsx
main.jsx --> layout.jsx
layout.jsx --> footer.jsx

entry_user --> page_user.html
page_user.html --> main.jsx
main.jsx -.-> user.jsx
user.jsx --> router_user.jsx
user.jsx --> navbar_user.jsx
main.jsx --> layout.jsx
layout.jsx --> footer.jsx

(dot arrows are dynamic imports)

If I have two entry point rollup is called only one time with multiple input ? because if called twice we could just change the given file when launching it.

Rollup will be called once with multiple inputs. If you want to call twice, you'll need to call Vite twice (e.g. npx vite build --mode user && npx vite build --mode admin). That would create two chunks, but would include duplicated code (i.e. chunks won't be shared).

@Et7f3
Copy link
Author

Et7f3 commented May 18, 2024

Rollup will be called once with multiple inputs.

Ok so I might first open an issue in upstream rollup (and esbuild ?) before it can be done in vite.

Native build tool provide this functionality by delaying object selection to link and optimize at link time. https://dune.readthedocs.io/en/stable/variants.html

@sapphi-red
Copy link
Member

sapphi-red commented May 19, 2024

A single rollup build creates a single module graph. What you are trying to build has two module graphs (one for user, one for admin). So you'll need to build twice.
Or you can organize your module graphs so it becomes a single module graph.

IIUC you want to create a single module graph from two module graphs. That's not supported by rollup and requires changes on rollup side. I'll close this issue for now.

@sapphi-red sapphi-red closed this as not planned Won't fix, can't repro, duplicate, stale May 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants