flow icon indicating copy to clipboard operation
flow copied to clipboard

Vite doesn't detect changes in files in target/flow-frontend

Open ggecy opened this issue 1 year ago • 10 comments

Description of the bug

We have a maven multimodule project where js/ts files from different maven modules end up in target/flow-frontend directory. Once the server is started for the first time (in development mode), vite creates the node_modules/.vite folder and it works. However any time I make a change in other modules and the updated file gets to target/flow-frontend, vite doesn't detect the change until I manually delete the node_modules/.vite directory and restart the server. We even have a custom file watcher implemented which copies the modified files from src/main/resources/META-INF/resources/frontend from other modules to target/flow-frontend even when the server is running - this caused webpack to reload the page and the changes were effective even without server restart. However this doesn't work with vite, not even with server restart.

Versions:

- Vaadin / Flow version: 23.2.2
- Java version: 17
- OS version: Mac OS 12.6
- Browser version (if applicable): Chrome 105.0.5195.125
- Application Server (if applicable): Spring boot 2.7.3 with embedded tomcat
- IDE (if applicable): Intellij IDEA
- Development or production mode: development

ggecy avatar Sep 29 '22 12:09 ggecy

Presumably Vite thinks it can cache the result forever as the files come from node_modules i.e. they are from an external dependency

Artur- avatar Sep 30 '22 07:09 Artur-

We are facing the same issue in our project. With webpack, we had to restart the server, so that changes in other modules were detected but now with vite, we have to execute mvn vaadin:clean-frontend on every change of a frontend file and restart the server after that.

probert94 avatar Oct 06 '22 14:10 probert94

It should be enough to remove node_modules/.vite and restart. Should be faster than a full clean

Artur- avatar Oct 06 '22 14:10 Artur-

If you set this in your vite.config.ts it should work

import { UserConfigFn } from 'vite';
import { overrideVaadinConfig } from './vite.generated';

const customConfig: UserConfigFn = (env) => ({
  // Here you can add custom Vite parameters
  // https://vitejs.dev/config/

  server: {
    watch: {
      ignored: ['!**/node_modules/@vaadin/flow-frontend/**'],
    },
  },
  optimizeDeps: {
    exclude: ['@vaadin/flow-frontend'],
  },
});

export default overrideVaadinConfig(customConfig);

Artur- avatar Oct 07 '22 06:10 Artur-

Thank you for providing a workaround @Artur- Do we still have to use custom file watcher like @ggecy has implemented for webpack or is that not needed anymore?

probert94 avatar Oct 07 '22 06:10 probert94

The fix will make Vite work like webpack worked. It will not solve any other multi module projects like when files are copied. For that the watcher can be useful

Artur- avatar Oct 07 '22 06:10 Artur-

Thanks for the information. @ggecy do you mind sharing some information about your file watcher solution?

probert94 avatar Oct 07 '22 06:10 probert94

If you set this in your vite.config.ts it should work

import { UserConfigFn } from 'vite';
import { overrideVaadinConfig } from './vite.generated';

const customConfig: UserConfigFn = (env) => ({
  // Here you can add custom Vite parameters
  // https://vitejs.dev/config/

  server: {
    watch: {
      ignored: ['!**/node_modules/@vaadin/flow-frontend/**'],
    },
  },
  optimizeDeps: {
    exclude: ['@vaadin/flow-frontend'],
  },
});

export default overrideVaadinConfig(customConfig);

Thank you - I have already tried to add this before I created the issue and it wasn't working, but I tried it again now and I realized it wasn't working because now (since our client side sources are excluded from optimizeDeps) I have to manually include all js libraries our code imports that need to be optimized (probably because it's using CommonJS modules or something) , otherwise the page will not load at all and there are weird vite javascript errors in browser developer tools console.

import { UserConfigFn } from 'vite';
import { overrideVaadinConfig } from './vite.generated';

const customConfig: UserConfigFn = (env) => ({
    // Here you can add custom Vite parameters
    // https://vitejs.dev/config/
    server: {
        watch: {
            ignored: ['!**/node_modules/@vaadin/flow-frontend/**']
        }
    },
    optimizeDeps: {
        exclude: ['@vaadin/flow-frontend'],
        include: ["ethers", "bwip-js"]
    }
});

export default overrideVaadinConfig(customConfig);

ggecy avatar Oct 07 '22 19:10 ggecy

Thanks for the information. @ggecy do you mind sharing some information about your file watcher solution?

I don't see any button to attach the file here, so I tried to share it on goodle drive: https://drive.google.com/file/d/1P-1umxNEKjkMxp2iBP0IFJbWOTr6R-jt/view?usp=sharing

The file is experimental, not a clean code, but it works... Feel free to modify it for your needs. It will try to find all META-INF/resources/frontend, META-INF/frontend and META-INF/resources/themes folders in any target folder of your modules on classpath and copies them to target/flow-frontend folder in your bootstrap module whenever it detects a change with slight delay to avoid duplicate activations. Also you need to press compile button in Intellij Idea if you modify your js/ts/css files in mentioned folders so they get copied to target (it doesn't watch the src folder). It doesn't do anything by itself, you need to register it as listener when starting your spring boot application:

public static void main(String[] args) {
        SpringApplication application = new SpringApplication(YourApplication.class);
        application.addListeners(new WebpackFrontendResourceExtractor());
        application.run(args);
    }

ggecy avatar Oct 07 '22 19:10 ggecy

Thank you very much. I am running an embedded jetty but the approach should probably be more or less the same. Thanks again :)

probert94 avatar Oct 07 '22 20:10 probert94

any updates ?

F0rce avatar Oct 30 '22 18:10 F0rce

The fix in #10373 does not work because of an issue in Vite so another approach is needed

Artur- avatar Nov 01 '22 07:11 Artur-

@Artur- does this fix change the way we import resources form other modules? I am currently using import { MyComponent } from "@vaadin/flow-frondend/my-component"

probert94 avatar Nov 03 '22 13:11 probert94

If you manually import, you would need to import from Frontend/generated/jar-resources/my-component instead

Artur- avatar Nov 03 '22 13:11 Artur-

With import, I mean import in frontend-files (*.ts or *.js). For example if my-other-component.ts should extend my-component.ts, at the moment I use the import statement import { MyComponent } from "@vaadin/flow-frondend/my-component" inside my-other-component.ts.

probert94 avatar Nov 03 '22 13:11 probert94

is there an eta for when it will reach upstream / be downloadable via maven ?

F0rce avatar Nov 03 '22 13:11 F0rce

It is not fully backwards compatible for all apps, as mentioned above with the imports, it goes into 23.3 (December)

Artur- avatar Nov 03 '22 14:11 Artur-

Thanks for the info @Artur-.

If you need someone to test a pre-release or rc, let me know. I develop a lot of add-ons (that's where the problem occurred for me) and could test it in more than one environment.

F0rce avatar Nov 03 '22 14:11 F0rce