ym-project / gulp-esbuild

gulp plugin for esbuild bundler
MIT License
42 stars 7 forks source link

The `pipe` argument for `createGulpEsbuild` does not work as expected: #16

Open Sanshain opened 1 year ago

Sanshain commented 1 year ago

First I use createGulpEsbuild as here:

const esBuild = createGulpEsbuild({
    pipe: true,
    incremental: true,
})

and inside tasks I have the following sequential data processing:

.pipe(someChanges())
.pipe(
  esBuild({
    bundle: true,
    mainFields: [
        "svelte", "browser", "module", "main"
    ],
    outdir: release ? './scripts/release' : "./scripts",
    format: 'iife',
    target: 'es6',
    write: true,
    loader: {
        '.svg': 'text',
        '.png': 'file',
    },
    plugins: [
        esbuildSvelte({
            preprocess: sveltePreprocess(),
        }),
    ],
})
)

The problem:

to ebuild(...) call the source data arrives without changes made in the stream inside the someChanges() plugin

However (!), the changes come if before esBuild I make a save using .gulp.dest('build.FS/src/') as here:

.pipe(someChanges())
.pipe(.gulp.dest('build.FS/src/'))
.pipe(
  esBuild({
     ...
  })
)

As far as I understand from readme that pipe argument is responsible for receiving data from the stream (by default is disabled):

piping allows you to receive data from other plugins via stream piping (example).

(in readme its named piping, but in source code there is pipe (I guess it hasn't been fixed yet))

Thus, I am prone to believe that there is some kind of bug here. But I did a little digging in the source code, and I didn't find exactly how this logic should work

ym-project commented 1 year ago

Hi @Sanshain

Firstly, you should not use write: true/false option because the plugin rewrite it to false anyway. Gulp works with virtual files so the plugin sets write: false to save changes in RAM (not in file system).

I need your gulp's configuration to reproduce the problem.

Sanshain commented 1 year ago

Hi, @ym-project

I guess that this problem appears for me when using the key bundle: true and I found a way to reproduce the problem in the simplest way: this repository has a section with examples, and there is an example of using piping with following options for gulp-esbuild:

.pipe(gulpEsbuild({
    loader: {
        '.ts': 'ts',
    },
}))
How it works in its original form: ### How it works in its original form: It works well: the result of such processing are two files: `index.js` and `cities.js` with replaced cities: "London" and "New York" instead of "GULP_CITY1" and "GULP_CITY2" inside "cities.js". cities.js: ```js export const cities = [ "London", "New York" ]; ``` `index.js`: ```ts import { cities } from "./cities"; cities.forEach((city) => console.log(`From ${city} with love.`)); ``` It`s ok!

Problem reproduction:

Now, if I add an option bundle: true, then I get cities.js with replaced names and index.js with unchanged values:

.pipe(gulpEsbuild({
        bundle: true,
    loader: {
        '.ts': 'ts',
    },
}))

cities.js (iife is ok):

(() => {
  // src/cities.ts
  var cities = [
    "London",
    "New York"
  ];
})();

and index.js (problem):

(() => {
  // src/cities.ts
  var cities = [
    "GULP_CITY1",
    "GULP_CITY2"
  ];

  // src/index.ts
  cities.forEach((city) => console.log(`From ${city} with love.`));
})();

Thus, it turns out that for processing the file index.ts esbuild took the source contents of the file cities.ts (with unchanged city names) - not from the stream.

ym-project commented 1 year ago

It seems like esbuild reads files from file system when these files come from import or require statements. I think I can not fix this because the problem concerns the esbuild.

I will create an issue in esbuild repository and ask the author about this. Maybe he will help us.

ym-project commented 1 year ago

Hi @Sanshain again!

I created an issue and the author of esbuild gave the advise. He suggested to create a plugin which will intercept file import and replace their content.

I'll think how to implement it.

FlyveHest commented 1 year ago

I had (or, have) the same problem, but I worked around it by using the esbuild-plugin-text-replace plugin.

Using this I could replace text in all files passing through esbuild, before they were parsed.