'Rollup preserveModulesRoot not working as expected

I feel like the preserveModulesRoot option while using preserveModules does not work as it should. Let's say I have a src/index.ts and a bunch of src/components/CompXYZ.tsx files. What I expect to happen with the preserve modules and root set to src is for my build to look like this:

dist
-- index.js
-- index.map.js
-- index.d.ts
-- components
---- CompA.js
---- CompA.map.js
---- CompA.d.ts
---- CompB.js
---- CompB.map.js
---- CompB.d.ts

But what actually happens is that the src prefix is stripped only from the input.ts file and no other so the build ends up looking like this:

dist
-- index.js
-- index.map.js
-- index.d.ts
-- components
---- CompA.d.ts
---- CompB.d.ts
-- src
---- components
------ CompA.js
------ CompA.map.js
------ CompB.js
------ CompB.map.js

So it looks like preserveModulesRoot only affect modules mentioned in input option but if I was to manually write out all the modules one by one, I can just place them where I want instead of using the preserveModulesRoot. What's the point of this setting if not to set root for all additional modules created with preserveModules enabled?

Here is my rollup.config.js

import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import typescript from 'rollup-plugin-typescript2';
import postcss from 'rollup-plugin-postcss';
import image from '@rollup/plugin-image';

export default {
    input: 'src/index.ts',
    output: {
        dir: 'dist',
        format: 'esm',
        sourcemap: true,
        preserveModules: true,
        preserveModulesRoot: 'src',
    },
    plugins: [
        peerDepsExternal(),
        resolve(),
        commonjs(),
        typescript(),
        postcss(),
        image(),
    ],
};


Solution 1:[1]

I dealt with the same thing when moving my build scripts from the root of a monorepo to a package within it. I think the issue might be due to this section of code: https://github.com/rollup/rollup/blob/5a5391971d695c808eed0c5d7d2c6ccb594fc689/src/Chunk.ts#L460-L464

Without the complete path:

              preserveModules: true,
              preserveModulesRoot: `packages/${displayName}/src`

yields a dist/ folder like this:

without complete path

With the complete path we want removed:

                preserveModules: true,
                preserveModulesRoot: path.join(process.env.PROJECT_CWD, `packages/${displayName}/src`)

yields a dist/ folder like this (which seems like it's more like what you were expecting):

with complete path

FYI: displayName prop is coming from the package.json of each individual package.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Rachel Cantor