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

Is it possible to make this plugin transpile files from outside the root of the package (f. ex. in a monorepo setup)? #216

Closed
goepi opened this issue Mar 17, 2020 · 8 comments
Labels
kind: bug Something isn't working properly kind: feature New feature or request scope: upstream Issue in upstream dependency topic: monorepo / symlinks Related to monorepos and/or symlinks (Lerna, Yarn, PNPM, Rush, etc)

Comments

@goepi
Copy link

goepi commented Mar 17, 2020

Here is a repo created just to show this issue

In a monorepo, where a root repository has a directory called packages with two npm packages in it, if each of the packages has a rollup config (that uses rollup-plugin-typescript2) and they both refer to a tsconfig at the root that defines paths so that the packages can import each other using absolute paths, how is it possible to build one of the packages without building the other (assuming the first one you build depends on the other?

Here is a SO question for this. I am posting it here as well because I think that as monorepos become more prevalent, this will become something important to add to either the capability of this plugin or its documentation.

@ezolenko
Copy link
Owner

Out of the box you could do something with separate rollup configs for each package and separate tsconfigs for each, that include only that package. You can still have most of ts configuration shared using base tsconfg.

So instead of doing tsconfig: '../../tsconfig.json' in rollup config, you drop tsconfig in each package that "extends" root tsconfig { "extends": "../../tsconfig.json" }. This sets up source root and other typescript magic.

If it works and you nail down details, let me know I'll add a section to readme (or make a PR). Working example test repo would be ideal as a reference.

@goepi
Copy link
Author

goepi commented Mar 17, 2020

I have linked an example repo above.

But what would having a tsconfig in each package do that's different from just telling rollup to look at tsconfig in the root of the monorepo? What kind of magic are we talking about?

How would having an own tsconfig make rollup transpile source files from outside the package? This is precisely the issue that plugin typescript2 is giving: it doesn't transpile outside files.

I tested adding a tsconfig to the package, but I still get the same error.
image

@ezolenko
Copy link
Owner

Location of the leaf tsconfig is root of all relative paths for typescript (including for default include/exclude patterns). The plugin feeds tsconfig to typescript and gets list of files that typescript found and only processes them if rollup feeds them in (also affected by plugin's own include/exclude patterns).

I guess I misunderstood what you want to do. Looks like you are including files from other packages directly. That effectively turns them from isolated packages into subfolders of the same package.

I see two ways to structure it cleanly:

  1. packages are isolated, only refer to public API of each other (same way an external client would use them from npm)
  2. all source code is intermingled, organized in folders, but any file is freely referring to any other file, several bundles are built from that for external consumption

If first case you need separate tsconfigs. So when building, typescript and rollup only see source for the package being built. When another package is needed, it is built and build result is imported.

In second case you need common tsconfig that sees all source files, and can use root rollup config with multiple bundles defined. In this case build artifacts are never used internally.

Looks like you are going for the second case. I can't run your test repo (yarn run build fails to find rollup, looks like it expects it installed globally?).

To debug, set plugin verbosity to 3 and check if typescript finds all files you are expecting. If util/src/index.ts is not in the list of files in parsed tsconfig, tweak include paths there. Post the output here as well.

@goepi
Copy link
Author

goepi commented Mar 17, 2020

Thanks. Sorry, I updated the readme. After you yarn install you must yarn lerna:bootstrap, and then rollup will be installed. Then you can yarn build.

@goepi
Copy link
Author

goepi commented Mar 17, 2020

Below is the full output with verbosity:3, when I try to bundle with rollup based on the single root tsconfig.

Note that utils/index.ts is included in the list of fileNames of the parsed tsconfig. This is what I don't understand. It's there so why is it not transpiled?

< log:
rpt2: built-in options overrides: {
    "noEmitHelpers": false,
    "importHelpers": true,
    "noResolve": false,
    "noEmit": false,
    "inlineSourceMap": false,
    "outDir": "/Users/goepi/Projects/snippets/lru-test/packages/component-library/node_modules/.cache/rollup-plugin-typescript2/placeholder",
    "moduleResolution": 2,
    "allowNonTsExtensions": true,
    "module": 5
}
rpt2: parsed tsconfig: {
    "options": {
        "jsx": 2,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "moduleResolution": 2,
        "allowJs": true,
        "baseUrl": "/Users/goepi/Projects/snippets/lru-test",
        "paths": {
            "@project/*": [
                "packages/*/src"
            ]
        },
        "configFilePath": "/Users/goepi/Projects/snippets/lru-test/packages/component-library/../../tsconfig.json",
        "noEmitHelpers": false,
        "importHelpers": true,
        "noResolve": false,
        "noEmit": false,
        "inlineSourceMap": false,
        "outDir": "/Users/goepi/Projects/snippets/lru-test/packages/component-library/node_modules/.cache/rollup-plugin-typescript2/placeholder",
        "allowNonTsExtensions": true,
        "module": 5
    },
    "fileNames": [
        "/Users/goepi/Projects/snippets/lru-test/prettier.config.js",
        "/Users/goepi/Projects/snippets/lru-test/applications/test-app/src/App.test.tsx",
        "/Users/goepi/Projects/snippets/lru-test/applications/test-app/src/App.tsx",
        "/Users/goepi/Projects/snippets/lru-test/applications/test-app/src/index.tsx",
        "/Users/goepi/Projects/snippets/lru-test/applications/test-app/src/serviceWorker.ts",
        "/Users/goepi/Projects/snippets/lru-test/applications/test-app/src/setupTests.ts",
        "/Users/goepi/Projects/snippets/lru-test/packages/component-library/rollup.config.js",
        "/Users/goepi/Projects/snippets/lru-test/packages/component-library/src/MyComponent.tsx",
        "/Users/goepi/Projects/snippets/lru-test/packages/component-library/src/index.tsx",
        "/Users/goepi/Projects/snippets/lru-test/packages/styles/rollup.config.js",
        "/Users/goepi/Projects/snippets/lru-test/packages/styles/src/index.js",
        "/Users/goepi/Projects/snippets/lru-test/packages/utils/rollup.config.js",
        "/Users/goepi/Projects/snippets/lru-test/packages/utils/src/index.ts"
    ],
    "typeAcquisition": {
        "enable": false,
        "include": [],
        "exclude": []
    },
    "raw": {
        "compilerOptions": {
            "jsx": "react",
            "esModuleInterop": true,
            "allowSyntheticDefaultImports": true,
            "moduleResolution": "node",
            "allowJs": true,
            "baseUrl": ".",
            "paths": {
                "@project/*": [
                    "packages/*/src"
                ]
            }
        },
        "exclude": [
            "**/build/**"
        ],
        "compileOnSave": false
    },
    "errors": [],
    "wildcardDirectories": {
        "/users/goepi/projects/snippets/lru-test": 1
    },
    "compileOnSave": false,
    "configFileSpecs": {
        "includeSpecs": [
            "**/*"
        ],
        "excludeSpecs": [
            "**/build/**"
        ],
        "validatedIncludeSpecs": [
            "**/*"
        ],
        "validatedExcludeSpecs": [
            "**/build/**"
        ],
        "wildcardDirectories": {
            "/users/goepi/projects/snippets/lru-test": 1
        }
    }
}
rpt2: typescript version: 3.8.3
rpt2: tslib version: 1.10.0
rpt2: rollup version: 2.0.6
rpt2: rollup-plugin-typescript2 version: 0.26.0
rpt2: plugin options:
{
    "tsconfig": "../../tsconfig.json",
    "verbosity": 3,
    "check": true,
    "clean": false,
    "cacheRoot": "/Users/goepi/Projects/snippets/lru-test/packages/component-library/node_modules/.cache/rollup-plugin-typescript2",
    "include": [
        "*.ts+(|x)",
        "**/*.ts+(|x)"
    ],
    "exclude": [
        "*.d.ts",
        "**/*.d.ts"
    ],
    "abortOnError": true,
    "rollupCommonJSResolveHack": false,
    "useTsconfigDeclarationDir": false,
    "tsconfigOverride": {},
    "transformers": [],
    "tsconfigDefaults": {},
    "objectHashIgnoreUnknownHack": false,
    "cwd": "/Users/goepi/Projects/snippets/lru-test/packages/component-library",
    "typescript": "version 3.8.3"
}
rpt2: rollup config:
{
    "experimentalCacheExpiry": 10,
    "external": [],
    "inlineDynamicImports": false,
    "input": "src/index.tsx",
    "perf": false,
    "plugins": [
        {
            "name": "commonjs"
        },
        {
            "name": "rpt2"
        },
        {
            "name": "stdin"
        }
    ],
    "strictDeprecations": false
}
rpt2: tsconfig path: /Users/goepi/Projects/snippets/lru-test/packages/component-library/../../tsconfig.json
rpt2: included:
[
    "*.ts+(|x)",
    "**/*.ts+(|x)"
]
rpt2: excluded:
[
    "*.d.ts",
    "**/*.d.ts"
]
rpt2: Ambient types:
rpt2:     /Users/goepi/Projects/snippets/lru-test/node_modules/@types/events/index.d.ts
rpt2:     /Users/goepi/Projects/snippets/lru-test/node_modules/@types/glob/index.d.ts
rpt2:     /Users/goepi/Projects/snippets/lru-test/node_modules/@types/minimatch/index.d.ts
rpt2:     /Users/goepi/Projects/snippets/lru-test/node_modules/@types/node/ts3.2/index.d.ts
rpt2: ambient types changed, redoing all semantic diagnostics
rpt2: transpiling '/Users/goepi/Projects/snippets/lru-test/packages/component-library/src/index.tsx'
rpt2:     cache: '/Users/goepi/Projects/snippets/lru-test/packages/component-library/node_modules/.cache/rollup-plugin-typescript2/rpt2_a5374387ed192686a0b838cf50fec73f5b55a241/code/cache/300ab513e25b87d0e92a46c7f61f1c797b8d4749'
rpt2:     cache miss
rpt2:     cache: '/Users/goepi/Projects/snippets/lru-test/packages/component-library/node_modules/.cache/rollup-plugin-typescript2/rpt2_a5374387ed192686a0b838cf50fec73f5b55a241/syntacticDiagnostics/cache/300ab513e25b87d0e92a46c7f61f1c797b8d4749'
rpt2:     cache miss
rpt2:     cache: '/Users/goepi/Projects/snippets/lru-test/packages/component-library/node_modules/.cache/rollup-plugin-typescript2/rpt2_a5374387ed192686a0b838cf50fec73f5b55a241/semanticDiagnostics/cache/300ab513e25b87d0e92a46c7f61f1c797b8d4749'
rpt2:     cache miss
rpt2: dependency '/Users/goepi/Projects/snippets/lru-test/packages/component-library/src/MyComponent.tsx'
rpt2:     imported by '/Users/goepi/Projects/snippets/lru-test/packages/component-library/src/index.tsx'
rpt2: resolving './MyComponent' imported by '/Users/goepi/Projects/snippets/lru-test/packages/component-library/src/index.tsx'
rpt2:     to '/Users/goepi/Projects/snippets/lru-test/packages/component-library/src/MyComponent.tsx'
rpt2: transpiling '/Users/goepi/Projects/snippets/lru-test/packages/component-library/src/MyComponent.tsx'
rpt2:     cache: '/Users/goepi/Projects/snippets/lru-test/packages/component-library/node_modules/.cache/rollup-plugin-typescript2/rpt2_a5374387ed192686a0b838cf50fec73f5b55a241/code/cache/c57c71cf282ed7d75d033fb7f64a31860fe5550c'
rpt2:     cache miss
rpt2:     cache: '/Users/goepi/Projects/snippets/lru-test/packages/component-library/node_modules/.cache/rollup-plugin-typescript2/rpt2_a5374387ed192686a0b838cf50fec73f5b55a241/syntacticDiagnostics/cache/c57c71cf282ed7d75d033fb7f64a31860fe5550c'
rpt2:     cache miss
rpt2:     cache: '/Users/goepi/Projects/snippets/lru-test/packages/component-library/node_modules/.cache/rollup-plugin-typescript2/rpt2_a5374387ed192686a0b838cf50fec73f5b55a241/semanticDiagnostics/cache/c57c71cf282ed7d75d033fb7f64a31860fe5550c'
rpt2:     cache miss
rpt2: resolving 'react' imported by '/Users/goepi/Projects/snippets/lru-test/packages/component-library/src/MyComponent.tsx'
rpt2:     to '/Users/goepi/Projects/snippets/lru-test/packages/component-library/node_modules/react/index.js'
rpt2: resolving '@project/utils' imported by '/Users/goepi/Projects/snippets/lru-test/packages/component-library/src/MyComponent.tsx'
rpt2:     to '/Users/goepi/Projects/snippets/lru-test/packages/utils/src/index.ts'

@goepi
Copy link
Author

goepi commented Mar 17, 2020

@ezolenko regarding the why of doing this

  • lets say these packages were in larger number and some were dependencies of others
  • say you work on one of the packages, and run it locally; then you make changes to another package it depends on, also in the same monorepo; if the first package is pointing to the source of the second package, you can immediately see the results of making changes to the second package on the first package, without having to rebuild the second package.
  • in CI, the build would happen a different way, from node_modules

@ezolenko
Copy link
Owner

Do you get exactly the same error when using single tsconfig? I don't see error in your verbose output.

For your reasons, the problem you might have is CI and release builds will be different from your dev builds. For example in case a package doesn't export something internal, but you imported and used it directly. Using different dependency chains for dev and production builds is a bad idea in general.

Pure typescript (without rollup) can deal with it by building subprojects on demand. Doing the same with rollup based subprojects will involve some plumbing I expect...

@agilgur5
Copy link
Collaborator

This works with the current version of rpt2!

So I was investigating #295, which roughly duplicates this issue, and it turns out this is already possible with a newer version of rpt2 (the original issue uses 0.26.0).

root cause is actually due to upstream @rollup/pluginutils

Per #295 (comment), this actually boils down to what might be a considered a bug in upstream @rollup/pluginutils, which is what is responsible for filtering out files.
pluginutils v4 released rollup/plugins#517, which removed the process.cwd() that it was putting in front of nearly all paths -- the addition of process.cwd() upstream made it difficult to include files outside of the project root (I think changing the plugin include could have worked with a very specific configuration? not 100% sure).

Upgrade to v0.30.0+ (or ideally, just latest)

rpt2 version 0.30.0 upgraded @rollup/pluginutils to v4+, so if you use rpt2 0.30+ you should be able to transpile files outside of the package root.

I confirmed in the repro that installing rollup-plugin-typescript2@latest and then re-building will work and not throw any errors 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: bug Something isn't working properly kind: feature New feature or request scope: upstream Issue in upstream dependency topic: monorepo / symlinks Related to monorepos and/or symlinks (Lerna, Yarn, PNPM, Rush, etc)
Projects
None yet
Development

No branches or pull requests

3 participants