Skip to content

feat: modular (ddd) implementation - #4

Open
protibimbok wants to merge 5 commits into
masterfrom
modular
Open

protibimbok wants to merge 5 commits into
masterfrom
modular

Conversation

@protibimbok

@protibimbok protibimbok commented Nov 11, 2026 •

Copy link
Copy Markdown
Member

📑 Description

Implements goravel/goravel#1030

This is the Vite side of goravel/framework#1613. The plugin builds the application's modules and passes its @ alias table to the framework, so templates can name entries through an alias:

{{ vite "@/app.js" }}                    <!-- resources/js/app.js -->
{{ vite "@blog/app.js" }}                <!-- modules/blog/resources/js/app.js -->
{{ viteAsset "@/../images/logo.svg" }}   <!-- resources/images/logo.svg -->

Modules

artisan vite:inputs now reports the application's modules:

"modules": [{"name": "blog", "path": "modules/blog", "entries": ["modules/blog/resources/js/app.js"], "aliases": {"@blog-assets": "modules/blog/resources/assets"}}]

For each module, the plugin:

  • builds its entries (ViteEntries()), even if no view references them;
  • aliases @<name> to <path>/resources/js when that directory exists;
  • adds the aliases the module declares (ViteAliases()). A module can replace its own @<name> this way;
  • with refresh: true, also watches <path>/resources/views, <path>/routes and <path>/lang when they exist. If refresh is set to anything else, it is used as given.

An alias with the same name in the user's resolve.alias takes precedence over a module's. validateInputs accepts the new optional modules key, and output without it (from a framework that has no modules) works as before.

Alias table handed to the framework (src/aliases.ts)

  • collectAliases collects every resolve.alias whose name is a string starting with @ and whose replacement is a directory inside the project. That includes the plugin's own @ and the user's. Patterns, node_modules and directories outside the project are left out. When two aliases share a name, the first one wins, as in Vite.
  • Build: writeBundle adds the table to the manifest under the reserved key "goravel:aliases". No chunk can use that key because it contains a colon. SSR builds and builds with manifest: false are skipped.
  • Dev: the hot file is now one line of JSON, {"url": "http://localhost:5173", "aliases": {"@": "resources/js"}}, instead of the bare URL.
  • resolveEntry resolves discovered inputs and assets the same way the framework does. It strips the leading slash, replaces the longest alias that matches at a path boundary (so @ never captures @blog/…), and cleans . and ... That way, an entry written two different ways is built only once, and the manifest keys match what the framework looks up. If no alias matches an @ entry, or a path leaves the project, the build fails with a clear error.
  • collectAliases, resolveAlias and resolveEntry are exported for tools that build the discovered option themselves.

Other

  • packageManager is pinned to pnpm@12.18.0 exactly, and pnpm-lock.yaml is updated to match.
  • README sections "Modules" and "Aliases in templates", plus a CHANGELOG entry.

⚠️ Compatibility

The hot file format changed from a bare URL to JSON. A framework release that includes goravel/framework#1613 reads both formats. An older framework would treat the JSON line as a URL, so this plugin version requires that framework release.

✅ Checks

  • Added test cases for my code

vite:inputs gains "modules": [{name, path, entries, aliases}], every
path
relative to the project root, so goravel-vite-plugin can build module
entries, add the @<name> aliases and watch module directories. Without a
registry (legacy Boot) the list is empty.

- Entries come from ProvidesViteEntries; a module without any is still
  listed, the plugin needs its path.
- Aliases come from ProvidesViteAlias. A key must look like @<name> and
  its
  target must stay inside the module (ModularViteAliasInvalid); a key
  used
  by two modules, or equal to another module's implicit @<name>, fails
  with
  ModularViteAliasDuplicate. A module may redefine its own @<name>.
- A third-party module whose published copy is missing, differs from the
  linked version or is not owned by modular:publish fails the command
  (ModularModuleNotPublished, ModularModulePublishStale,
  ModularPublishTargetNotOwned), so Vite never builds without its
  sources
  or with old ones.

NewInputsCommand takes the module registry as a fourth argument.
Entries and assets may be written through a Vite alias, in templates and
in
Go: {{ vite "@/app.js" }}, {{ vite "@blog/app.js" }},
{{ viteAsset "@blog/../assets/logo.svg" }}.

goravel-vite-plugin owns the alias table and hands it over in the two
files
the framework already reads: the manifest, under the reserved key
"goravel:aliases", and the hot file, which becomes
{"url": "...", "aliases": {...}}. A hot file holding a bare URL still
works,
without aliases.

Tags, Asset and Content strip the leading slash, replace the longest
alias
matching at a path boundary (ViteAliasNotFound when none does), then
clean
the path and refuse one that leaves the project
(ViteEntryOutsideProject).
Leaving the alias directory while staying inside the project is allowed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant