Skip to content
This repository has been archived by the owner on Jan 18, 2022. It is now read-only.

Recursive vue imports with inline typescript #260

Closed
ezolenko opened this issue Jan 14, 2019 · 6 comments
Closed

Recursive vue imports with inline typescript #260

ezolenko opened this issue Jan 14, 2019 · 6 comments
Labels
stale No activity for long

Comments

@ezolenko
Copy link

Expected behavior

Ideally rollup-plugin-vue handles all inline vue imports and creates multiple ?rollup-plugin-vue=script.ts modules in rollup before passing them down the chain.

Actual behavior

See ezolenko/rollup-plugin-typescript2#129, basically rollup-plugin-vue generates typescript code that gets passed to rollup-plugin-typescript2, but that code has another import "something.vue" statement and I can't pass it back to rollup because typescript demands cold hard values and doesn't take promises.

Steps to reproduce the behavior

See the test repo in the referenced bug.

@znck
Copy link
Member

znck commented Jan 15, 2019

Shouldn't ts-loader be running into this situation too?

@ezolenko
Copy link
Author

I don't know how webpack resolves things internally and how they deal with vue imports, so I can't say if they should have a similar problem. Looks like they use a sync version of webpack's resolver with the same typescript API in the end. Doesn't looks like there is an alternative in rollup.

I'm also looking into possibly preprocessing files to detect imports, sending them off to rollup resolver (which would hit vue plugin and cause it to generate new module), then using those resolutions. This might be a problem if I can't request module source from rollup from within transform call.

@znck
Copy link
Member

znck commented Jan 15, 2019

This might be a problem if I can't request module source from rollup from within transform call.

Let me know if you some approach, maybe I can help.

@ezolenko
Copy link
Author

ezolenko commented Jan 15, 2019

So the main problem is typescript not knowing what shape .vue module is, because inline script is not exposed yet. I don't see a good way to fix this without mixing areas of concern -- either rpt2 will need to know how to parse vue or vue plugin will need to know how to parse typescript (see below).

There are two flows currently (plugin order is not very important because we look at different file types):

  1. When starting from vue file:
component1.vue 
    => component1.vue?script=ts 
        => component2.vue 
            => component2.vue?script=ts
  • rollup starts the plugin chain
  • vue plugin extracts ts script and feeds ts code as a module to rollup
  • first chain ends there because rpt2 ignores .vue extension
  • rollup feeds new module to the chain
  • rpt2 processes new ts to js, that module is now visible to future transpiles
    • complains about unknown type of component2.vue module unless silenced by //@ts-ignore
  • rollup detects imports in js and starts the chain for each of them
  1. When starting from typescript file (is that a valid scenario?):
main.ts 
    => component1.vue 
        => component1.vue?script=ts 
            => component2.vue 
                => component2.vue?script=ts
  • rollup starts the plugin chain
  • rpt2 plugin transforms ts to js
    • complains about unknown type of component1.vue module unless silenced by //@ts-ignore
  • rollup detects imports in js and starts the chain for each of them
  • vue plugin handles component1.vue and injects a new ?script=ts module
  • ...

Vue plugin could do the preprocessing when it first extracts typescript source -- there is ts.preProcessFile function that looks like it will return imported files (hopefully it will not try to resolve them on its own, otherwise we are back where we started). This will involve importing typescript (and expecting it in plugin options in case user wants a custom typescript version).

Vue plugin can check if any imports are vue and handle them recursively creating new modules for the whole tree, preferably leaves first.

If rollup preserves order when serving new modules, flattened depth first dependency tree will handle first scenario.

Scenario 2 is worse because typescript only knows about dynamic modules when transform() on rpt2 is called and they are added to the known file list and to document registry. Even if vue plugin reads initial ts code, gets all imports and extracts all the modules in correct order, they will become available on the next iteration, which is too late.

declare namespace ts {
    function preProcessFile(sourceText: string, readImportFiles?: boolean, detectJavaScriptImports?: boolean): PreProcessedFileInfo;
}
   interface PreProcessedFileInfo {
        referencedFiles: FileReference[];
        typeReferenceDirectives: FileReference[];
        libReferenceDirectives: FileReference[];
        importedFiles: FileReference[];
        ambientExternalModules?: string[];
        isLibFile: boolean;
    }

@znck
Copy link
Member

znck commented Jan 16, 2019

cc: @Rich-Harris

@ezolenko
Copy link
Author

There is a parallel discussion here too: ezolenko/rollup-plugin-typescript2#129

@znck znck added the stale No activity for long label Nov 21, 2019
@znck znck closed this as completed Nov 21, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
stale No activity for long
Projects
None yet
Development

No branches or pull requests

2 participants