Problem/Motivation
Currently, the module operates with the assumption that vite is configured per module/theme and resolves paths relative to the module/theme dir. While it works fine, in some cases it would be more convenient to create a single vite configuration for the entire project (instead of separate configs for each module/theme) and place it, for example, in the project root.
Proposed resolution
- allow configuring vite root dir (with default value of theme/module dir)
- resolve paths relative to vite root
- deprecate manifestPath config option in favor of a new distDir config option that will be the same as the build.outDir in vite config (vite manifest file is always in the same location in the dist/out directory)
- automatically resolve dist asset paths relative to drupal app root so that there's no need to configure baseUrl
With these changes, configuring vite setup in project root dir with dist output in libraries dir could look like this:
/vite.config.js
/web/...
/web/themes/custom/my_theme/...
/web/themes/custom/my_theme/ts/script.ts
# settings.php
$settings['vite']['viteRoot'] = '/..'; # if starts with / it's resolved relative to Drupal app root, othervise relative to theme/module dir
$settings['vite']['distDir'] = 'web/libraries/dist/';
# this can also be configured on per extension/library basis in .info.yml or .libraries.yml same as other configuration options
# web/themes/custom/my_theme/my_theme.info.yml
...
vite:
enableInAllLibraries: true
# web/themes/custom/my_theme/my_theme.libraries.yml
my_library:
js:
ts/script.ts: {}
Remaining tasks
- add automated tests for the new config options
- update error messages to account for new config options
- add warning when distDir is configured outside drupal app root
- create follow-up for adding automatic detection of distDir based on regexing vite.config.(ts|js) in viteRoot
- create follow-up for removing deprecated manifestPath config option
Issue fork vite-3511730
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
wotnakPushed initial implementation of the proposed solution to MR !22.
Still needs more testing, some cleanup, docs and automated test.
It adds a new `viteRoot` config option that defaults to extension directory but can be set to for example, project root. If the value starts with /, then it is resolved relative to drupal root, otherwise relative to the extension dir.
The vite root path is then used to resolve path to manifest (configured manifest path is treated as relative to vite root) and paths to assets.
For example, to use setup with vite configured in project root and dist files generated to libraries dir (web/libraries/dist) we just need to set vite root to /.. and manifest path to web/libraries/dist/.vite/manifest.json.
Comment #4
wotnakAdded another config option `distPath` that should be set to dist directory path relative to vite root, the same as the build.outDir in vite config. The `manifest` config option is now deprecated in favor of `distPath` since vite manifest file is always in the same location in the dist directory.
Tests currently pass locally in an actual project but fail in gitlab ci because of the symlinked module source. Will probably need to replace `realpath` usage when resolving paths to skip resolving symlinks.
Comment #5
wotnakRecent changes:
Also updated IS to match the proposed resolution to the current approach and to add remaining tasks.
I will work on adding tests, but otherwise this should be ready for a review.
Comment #6
wotnakComment #9
reinfate commentedTested the changes in a real project with Vite configured in the project root (originally project has multiple webpack setups)
Seems to work as expected. All entries are properly attached to the page.
I see the issue is assigned, but I tried to write a test anyway and pushed it in a separate branch just in case.
One issue I came across.
\Drupal\Tests\vite\ViteKernelTestBase::assertLibraryAssetPathexpects the file to always be relative to the module root, even if viteRoot is outside the module. That works for libraries since\Drupal\vite\Vite::resolveDistAssetPathmakes a library file path relative to the module. But, for components, files are relative to the core directory.So I've added an optional parameter for
assertLibraryAssetPathto indicate the viteRoot path.I think it would be nicer if all paths were absolute, unless I don't see a reason why paths should be relative. Especially with vite in the project root, the links in the HTML look weird, because there is a lot of
..in the path in that case.Comment #10
reinfate commentedI noticed that @vite/client resolved with the absolute path to the vite contrib module if the vite root is globally configured to another path. For example, if Vite root is modules/custom, the generated link is
{devServerUrl}/var/www/html/web/modules/contrib/vite/@vite/client.Funny thing, if any CSS is included in the page, it will import the @vite/client itself, so the HMR will work anyway in that case.
Fixed that in MR !25
I guess this needs review now.
Comment #11
mh_nichtsHello,
Just to say I tested the last MR (25) on a local test project and it worked for me, with Vite config at the root of the project.
One note though : as I'm using DDEV , I had to add
root: 'web'in the config file, on top of following the instructions on https://www.drupal.org/docs/extending-drupal/contributed-modules/contrib... .This
rootparameter seems necessary for the manifest paths to match the server expectations (= the manifest paths should not contain "web/").Comment #12
darvanenWe closed #3490107: Make settings override for manifest an absolute value in favour of this approach.
I've finally got around to trying it out and I have a problem.
All the assets are being optimised and the chunk addresses in the built JS are relative so the browser is throwing a heap of 404s.
How did y'all stop Drupal from optimising your built assets?
Also, I had to spend a long time with xdebug to figure out how the settings were supposed to work for this.
Comment #13
darvanenI've added a commit to generate some discussion here, it may end up being reverted and that's fine, but I do not understand anyone is getting their vite server to compile to an absolute location and keeping their library paths relative to the various modules/themes?
Because we're compiling at root, all our of custom libraries reference their entrypoints from root, which allows the vite server to scan the library files for entrypoints, and create a manifest which transforms those absolute paths into a dist path.
Am I missing something simple here?
As for the aggregation, it seems the only way to get Drupal to avoid doing that is to mark a file asedit: I was using code related to an old aggregator, I see the bypass is nowtype: externalwhich directly conflicts with shouldBeManagedByVite(), so I'm going to open a core issue to address that because there needs to be another bypass in my opinion.preprocess: falseComment #14
darvanenI see that failed testing, can someone help me understand how this is supposed to work? I'm guessing we continue to follow the convention of relative links within library yml files - how do you get your vite server to
js/table.entry.jsfiles in different modulesComment #15
wotnak@darvanen
An example configuration with ViteJS setup in the project root for compiling assets in custom themes and modules could look like this:
Configure ViteJS
In vite.config.js:
Configure custom themes/modules
In theme/module.info.yml:
In theme/module.libraries.yml:
How Vite module works
In this example, the Vite module will:
Comment #16
wotnak@reinfate
Tests and fix for @vite/client look good. Thanks.
Comment #18
wotnakReverted the last commit that broke the functionality and pushed small fixes for issues reported by phpstan.
I'm already using changes from the MR on a few work projects, and it works fine.
Since reinfate and mh_nichts also reported that the changes work for them, I think we can merge this.
And maybe as a follow-up in a separate issue, work on adding some examples to the docs to make it easier to start using functionality added in this issue and the module in general.
Comment #20
wotnakMerged and released in 1.5.0.
Comment #22
darvanen@wotnak how do you reliably prevent name collisions in your manifest?Never mind, I was confused to start with.