admin管理员组

文章数量:1361960

We are using the "not-so-new" build system for Angular applications (ESBuild) and we need to execute a node script before each Angular build (or rebuild). This script will generate a custom ts file that is imported in some of the apps components.

We would like to avoid redefining all npm tasks involved (serve, build, start, etc.) to prepend node script.js && , and instead integrate the script execution with the build process.

Based on the approved answer to the question "How to execute a script before each angular compilation (esbuild)?" it seems that developing a custom esbuild plugin would be the way to go.

As per our understanding, the default "application" builder does not allow to use ESBuild plugins, so we have loaded custom-esbuild builder and defined a plugin "generateFile" :

import { exec } from 'child_process';

const generateFile = {
  name: 'generate-file',
  setup(build) {
    build.onEnd(() => {
      console.log('Launching script scripts/generate-file.js...');
      
      exec('node scripts/generate-file.js', (error, stdout, stderr) => {
        if (error) {
          console.error('Error:', error.message);
          return;
        }
        if (stderr) {
          console.error('Error:', stderr);
        }
        console.log(stdout);
      });
    });
  },
};

export default [generateFile];

This works just fine and executes generate-file.js node script and generates the corresponding file (lets call it "generated-file.ts").

The issue arises on watch mode. When we change any component:

  • ESBuild detects that a file has changed, so it launches the build again.
  • the plugin launches the node script generate-file (again).
  • generate-file generates the "generated-file.ts" (again)
  • ESBuild detects that a file has changed (because generated-file.ts has changed) which triggers a new rebuild
  • the plugin launches the node script generate-file (again), which generates the "generated-file.ts" (again) ...

... and so on, entering an infinite loop

Furthermore, it seems that there are no watch options for ESBuild, which would allow us to ignore some files on watch mode.

Is there any way to tell ESBuild to exclude generated-file from watch mode?

We are using the "not-so-new" build system for Angular applications (ESBuild) and we need to execute a node script before each Angular build (or rebuild). This script will generate a custom ts file that is imported in some of the apps components.

We would like to avoid redefining all npm tasks involved (serve, build, start, etc.) to prepend node script.js && , and instead integrate the script execution with the build process.

Based on the approved answer to the question "How to execute a script before each angular compilation (esbuild)?" it seems that developing a custom esbuild plugin would be the way to go.

As per our understanding, the default "application" builder does not allow to use ESBuild plugins, so we have loaded custom-esbuild builder and defined a plugin "generateFile" :

import { exec } from 'child_process';

const generateFile = {
  name: 'generate-file',
  setup(build) {
    build.onEnd(() => {
      console.log('Launching script scripts/generate-file.js...');
      
      exec('node scripts/generate-file.js', (error, stdout, stderr) => {
        if (error) {
          console.error('Error:', error.message);
          return;
        }
        if (stderr) {
          console.error('Error:', stderr);
        }
        console.log(stdout);
      });
    });
  },
};

export default [generateFile];

This works just fine and executes generate-file.js node script and generates the corresponding file (lets call it "generated-file.ts").

The issue arises on watch mode. When we change any component:

  • ESBuild detects that a file has changed, so it launches the build again.
  • the plugin launches the node script generate-file (again).
  • generate-file generates the "generated-file.ts" (again)
  • ESBuild detects that a file has changed (because generated-file.ts has changed) which triggers a new rebuild
  • the plugin launches the node script generate-file (again), which generates the "generated-file.ts" (again) ...

... and so on, entering an infinite loop

Furthermore, it seems that there are no watch options for ESBuild, which would allow us to ignore some files on watch mode.

Is there any way to tell ESBuild to exclude generated-file from watch mode?

Share Improve this question asked Apr 2 at 7:55 menrodriguezmenrodriguez 2953 silver badges7 bronze badges 3
  • You can create another function to check if the file exists or last updated time, if the check fails then you can create a new file. – Rohan Kumar Commented Apr 2 at 8:04
  • I understand there would be some problemas with that approach too: the file would be generated on first build (ok), on next rebuilds the check would fail based on the condition that the file exists (ok), but what if I stop the watch and relaunch it again? The file would not be updated (re-generated). You mention "last updated time", is there any way to know the time when a build was launched for first time so that I could check if the file has been created on the same cycle of build-watch-rebuild? – menrodriguez Commented Apr 2 at 8:15
  • You can try stackoverflow/a/41734257/1817690 and medium/@izzatnadiri/… to get the build version or timestamp from environment file. – Rohan Kumar Commented Apr 2 at 11:06
Add a comment  | 

1 Answer 1

Reset to default 0

We ended up changing the approach: instead of telling ESBuild to ignore a file on watch mode, we will not write the file if its content has not changed, like so:


const newContent = (...)

if (fs.existsSync(path)) {
  const currentContent = fs.readFileSync(path, 'utf8');
  if (currentContent === newContent) {
    process.exit(0);
  }
}

fs.writeFileSync(path, newContent);

本文标签: