First of all, thanks for writing/maintaining this handy plugin!
I tried implementing the incremental build/watch setup described in https://github.com/ym-project/gulp-esbuild/blob/v0/examples/watch/gulpfile.js. However, while the file is rebuilt, esbuild still operates with the initial file contents of streamed files, meaning the bundled file's contents are exactly the same as during the first iteration.
I looked into this behavior and it seems the new stream contents are discarded when a context has already been initialized:
params contains a plugin that returns the (updated) file contents:
|
plugins: [ |
|
resolvePlugin(entryPoints), |
|
...(esbuildOptions.plugins || []), |
|
], |
It is never actually passed to esbuild though (likely since rebuild is intended to run repeatedly with the same options):
|
// if it's the first build |
|
if (!ctx) { |
|
ctx = await context(params) |
|
} |
I was able to fix this issue via the following patch:
diff --git i/index.js w/index.js
index 0095fae..f2216f1 100644
--- i/index.js
+++ w/index.js
@@ -25,8 +25,12 @@ function createTransformStream(flushFn, entryPoints) {
if (!file.isBuffer()) {
return cb(createError(new TypeError('File should be a buffer')))
}
-
- entryPoints.push(file)
+ const fileIndex = entryPoints.findIndex((cfile) => cfile.path === file.path);
+ if (fileIndex >= 0) {
+ entryPoints[fileIndex] = file
+ } else {
+ entryPoints.push(file)
+ }
cb(null)
},
flush: flushFn,
@@ -106,10 +110,10 @@ function simpleBuild() {
function incrementalBuild() {
let ctx
+ /** @type Array<import('vinyl').BufferFile> */
+ const entryPoints = []
return function plugin(pluginOptions = {}) {
- /** @type Array<import('vinyl').BufferFile> */
- const entryPoints = []
const {metafileName, esbuildOptions} = splitOptions(pluginOptions)
async function flushFunction(cb) {
For reference, this is a trimmed-down version of my gulpfile.js:
const browserSync = require("browser-sync").create();
const { src, dest, watch, series, parallel } = require("gulp");
const gulpEsbuild = require("gulp-esbuild");
const incrementalGulpEsbuild = gulpEsbuild.createGulpEsbuild({
incremental: true,
});
const options = {
config: {
port: 9050,
},
paths: {
src: {
base: './src',
js: './src/js',
},
dist: {
base: './dist',
js: './dist/js',
},
}
}
function livePreview(done) {
browserSync.init({
server: {
baseDir: options.paths.dist.base,
},
port: options.config.port || 5000,
});
done();
}
function previewReload(done) {
browserSync.reload();
done();
}
function devScripts() {
return src(`${options.paths.src.js}/main.js`)
.pipe(
incrementalGulpEsbuild({
outfile: "app.js",
bundle: true,
target: "es2015",
platform: "browser",
})
)
.pipe(dest(options.paths.dist.js));
}
function watchFiles() {
// ...
watch(`${options.paths.src.js}/**/*.js`, series(devScripts, previewReload));
// ...
}
exports.default = series(
// ...
parallel(
devScripts,
// ...
),
livePreview,
watchFiles
);
First of all, thanks for writing/maintaining this handy plugin!
I tried implementing the incremental build/watch setup described in https://github.com/ym-project/gulp-esbuild/blob/v0/examples/watch/gulpfile.js. However, while the file is rebuilt, esbuild still operates with the initial file contents of streamed files, meaning the bundled file's contents are exactly the same as during the first iteration.
I looked into this behavior and it seems the new stream contents are discarded when a context has already been initialized:
paramscontains a plugin that returns the (updated) file contents:gulp-esbuild/index.js
Lines 121 to 124 in c5a65ee
It is never actually passed to
esbuildthough (likely sincerebuildis intended to run repeatedly with the same options):gulp-esbuild/index.js
Lines 135 to 138 in c5a65ee
I was able to fix this issue via the following patch:
For reference, this is a trimmed-down version of my
gulpfile.js: