Dschungelabenteuer / vite-plugin-entry-shaking

Mimic tree-shaking behaviour when importing code from an entry file in development mode.
MIT License
125 stars 8 forks source link

Plugin Config #61

Open AlexKrupko opened 6 days ago

AlexKrupko commented 6 days ago

What does the bug relate to?

Describe the bug

Hi there,

I have the following files in the project in ./src/utils:

Then it's imported with import {util1} from 'utils'; in other files.

I've tried this config -

EntryShakingPlugin({
    targets: [
        {
            glob: 'src/utils/*.ts',
        }
    ],
}),

But I got an error Uncaught SyntaxError: The requested module '/src/utils/index.ts' does not provide an export named 'util1'. And it really doesn't provide util1 because index.ts is empty.

To Reproduce

What am I doing wrong? Is it possible to use this plugin on my file/import/export file structure?

Vite version

5.4.11

Additional context

No response

Dschungelabenteuer commented 6 days ago

Hey!

    targets: [
        {
            glob: 'src/utils/*.ts',
        }
    ],

When using this glob pattern, you're actually telling this plugin that all three files (util1.ts, util2.ts and the index.ts are entry files. Which ends up with a circular resolution of cleaned-up files.

What you're probably looking to achieve here is to solely set the utils/index.ts as an entry file (not the other two files) so that whenever you import util1 from utils/index.ts in some random file, it actually resolves to utils/util1.ts instead of involving that index.ts which would also cause utils/util2.ts to be processed).

Using the following config should get you on the right track:

    targets: [
        {
            glob: 'src/utils/index.ts',
        }
    ],

Please let me know :)

Dschungelabenteuer commented 6 days ago

When using this glob pattern, you're actually telling this plugin that all three files (util1.ts, util2.ts and the index.ts are entry files. Which ends up with a circular resolution of cleaned-up files.

That being said, while my above suggestion is likely to help in your scenario, this shouldn't fail like that and the original (aka non-cleaned-up) version of util1.ts should be loaded instead of the cleaned-up one. I actually have a bunch of examples based on cross-entries scenarii so this still is worth investigating! Thank's for reporting!

AlexKrupko commented 6 days ago

Hi @Dschungelabenteuer, Thank you for the quick answer. Actually, I tried setting up only the index file as entry point with glob: 'src/utils/index.ts',, but it didn't help and I got again the error - The requested module '/src/utils/index.ts' does not provide an export named 'util1'... Also I went through your examples, tried a lot of different variants, but unfortunately I didn't get a working config.

Dschungelabenteuer commented 6 days ago

Here's a simple example using the information you provided!

Hopefully this helps spot any difference between both your scenario and my repro attempt?

EDIT:

The requested module '/src/utils/index.ts' does not provide an export named 'util1'...

Also, just for the record, if you're having that error after specifically setting index.ts as an entry file, this would suggest that the file you're importing util1 into is probably not being transformed by this plugin! Perhaps have you set some other config options such as ignorePatterns or overridden default extensions?

AlexKrupko commented 6 days ago

@Dschungelabenteuer, no, I don't have any other config options except targets.

But, I've found the reason why it doesn't work. There is only one difference between my code and your example. You use relative paths for imports, but we use the vite-tsconfig-paths in our project. We have "baseUrl": "./src", in tsconfig and import utils like import {util1} from 'utils'; I tried to change it to relative path ../utils and it works as expected.

Is there an option to config the baseUrl in your plugin? Or any other way to do it?

Dschungelabenteuer commented 6 days ago

Is there an option to config the baseUrl in your plugin? Or any other way to do it?

Unfortunately it 100% relies on Vite's own resolvers: they do all the path resolution work and this plugin never actually interacts with the tsconfig.json configuration by itself! Would you mind sharing the whole tsconfig.json file if possible (and TypeScript version just to be sure)?

AlexKrupko commented 5 days ago

Here is our tsconfig.app.json. TS version 5.6 / 5.7

{
    "compilerOptions": {
        "baseUrl": "./src",

        "target": "ES2020",
        "useDefineForClassFields": true,
        "lib": ["ES2023", "DOM", "DOM.Iterable"],
        "module": "ESNext",
        "skipLibCheck": true,

        /* Bundler mode */
        "moduleResolution": "bundler",
        "allowImportingTsExtensions": false, // disallow file extensions in imports
        "allowSyntheticDefaultImports": true,
        "isolatedModules": true,
        "moduleDetection": "force",
        "noEmit": true,
        "jsx": "react-jsx",
        "incremental": true,

        /* Linting */
        "strict": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "noFallthroughCasesInSwitch": true,
        "useUnknownInCatchVariables": true,
        "verbatimModuleSyntax": true // require `type` keyword for imports
    },
    "include": ["src"],
    "exclude": ["dist", "node_modules", "public"],
}
AlexKrupko commented 5 days ago

I solved the issue above by adding an alias:

        resolve: {
            alias: {
                utils: '/src/utils',
                hooks: '/src/hooks',
                // .....
            },
        },

But next we have more difficult structure with components:

And, it's imported with import {Component1} from 'components';

I tried the glob pattern with wildcard ./src/components/**/index.ts and alias templates: '/src/templates',. But unfortunately, it doesn't replace the paths correctly... I get an error Uncaught ReferenceError: Component1 is not defined because the import is just removed from the file.