web: Problems with symlinked dependencies in monorepos and phantom dependencies
Since @open-wc/testing-karma is deprecated I’m migrating to @web/test-runner.
There are 2 big incompatibilities with monorepos.
esbuild duplicates symlinked lit-html instances
This problem is related to https://github.com/Polymer/lit-element/issues/390. Lit-html module should only be imported once, otherwise it will render [object Object]
. The module loader should cache the first ‘lit-html’ call and server always the same module.
Note that preserveSymlinks: true
is necessary. Without it web-test-runner will complain that @open-wc/testing is outside of the project directory.
web-test-runner referencees phantom dependencies
web-test-runner assumes that node_modules
contains all explicit and implicit dependencies of the project. But this is incompatible with pnpm
.
Reproduction
The problems can be reproduced in this repo:
https://github.com/javier-garcia-meteologica/test-runner-lit-hml-monopero-symlink-issue
$ git clone https://github.com/javier-garcia-meteologica/test-runner-lit-hml-monopero-symlink-issue
$ cd test-runner-lit-hml-monopero-symlink-issue
$ rush install
$ rush build
$ cd lit-element-ts-esbuild
$ yarn run test
I modified the code to log this.shadowRoot.innerHTML
to the console. The tests will fail because lit-html is imported more than once and it’s rendering those pesky [object Object]
.
🚧 Browser logs:
<!---->[object Object]<!---->
<!---->[object Object]<!---->
<!---->[object Object]<!---->
<!---->[object Object]<!---->
❌ MyElement > increases the counter on button click
at: test/my-element.test.ts:16:44
TypeError: Cannot read property 'click' of null
at n.<anonymous> (test/my-element.test.ts:16:44)
rush
uses pnpm
as a package manager by default, but this repository had to switch to yarn
so that web-test-runner
finds phantom dependencies.
To replicate the problem of phantom dependencies, edit the file <monorepo_root>/rush.json
, uncomment "pnpmVersion"
and comment out "yarnVersion"
.
"pnpmVersion":"4.14.4",
//"npmVersion":"4.5.0",
//"yarnVersion":"1.9.4",
Now purge the monorepo and rebuild
$ rm <monorepo_root>/common/config/rush/yarn.lock
$ rush update --full --purge
$ rush build
Running tests will fail and the errors will look like these:
TypeError: Failed to resolve module specifier "@open-wc/testing-helpers". Relative references must start with either "/", "./", or "../".
TypeError: Failed to resolve module specifier "chai/chai.js". Relative references must start with either "/", "./", or "../".
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 15 (7 by maintainers)
Finally I found out which were the remaining problems and how to solve them. First,
preserveSymlinks: true
should NOT be used because the only way to solve non-hoisted pnpm dependencies is to resolve the symlinks and, from the resolved directory, traverse parent directories looking up for node_modules with those dependencies. Thanks to @LarsDenBakker package resolution in pnpm works fine withoutpreserveSymlinks
.Therefore, the configuration should be:
This will almost work, except it won’t resolve
lit-html
.That’s because @rollup/node-resolve assumes that deduplicated dependencies are placed in the main
node_modules
directory of our project.https://github.com/rollup/plugins/blob/0e4f0142a9c44074ae8a5df86f9442b119a9978c/packages/node-resolve/src/index.js#L109
Perhaps lit-html@2 won’t need to be deduped, but so far we have to deal with it. So if we have deduplicated dependencies we need to add them as dependencies or devDependencies of our main project, even if they are not used directly.
And that’s all, now everything should work!
Can you try with the latest test-runner/dev-server? I’ve made it possible to resolve modules to any location.