In case we are not using the build-in watch mode from parcel bundler, would be great to be able to rebuild the bundle without to have to rebuild the full bundle.
import * as ParcelBundler from 'parcel-bundler';
const bundler = new ParcelBundler('path/to/my/index.js', {
outDir: './dist',
watch: false,
});
bundler.bundle();
// some time a bit later, we change a file from the bundle so we trigger another build
bundler.bundle();
// but here the second bundle is identical to first one,
// so we would need a way to inform the bundler that something changed
Right now I found a hack, but since the code might change, it's not reliable for long terms solution:
await bundler.bundle();
// some time a bit later, we change a file from the bundle so we trigger another build
let asset = await bundler.resolveAsset(path_of_file);
await bundler.buildQueue.add(asset, true);
await bundler.bundle();
// now bundle is up to date
I am building transpiler to generate static html websites using JSX (without React).
See https://github.com/apiel/radka
Current use case is located in my watch mode script: https://github.com/apiel/radka/blob/master/src/dev.ts#L108
In this case, the build-in watch mode from parcel is not working. I need only to build a JS file and somehow because of my setup, the parcel watch mode was breaking (building for ever).
Parcel is supposed to determine by itself which assets changed.
a hack
Indeed 馃槃
This seems to work for me:
const fs = require("fs");
const ParcelBundler = require("parcel-bundler");
async function bundle() {
const bundler = new ParcelBundler("./index.js", {
outDir: "./dist",
watch: false,
logLevel: 1,
});
await bundler.bundle();
}
async function test(v) {
fs.writeFileSync("index.js", `module.exports = ${v};`);
await bundle(0);
}
(async function () {
await test(0);
console.log("bundle exports: ", require("./dist/index.js"));
delete require.cache[require.resolve("./dist/index.js")];
await test(1);
console.log("bundle exports: ", require("./dist/index.js"));
})();
Unfortunately it doesn't seem to detect any changes. I first thought this was because I first delete the folder containing all the files to bundle and then write them again, but even if I don't delete the folder, it still not detect change.
Also in your example, you re-build everything from scratch. Or this is not the goal, I only want to reload the file(s) that have been changing. I will update your example to fit my request:
const fs = require("fs");
const ParcelBundler = require("parcel-bundler");
const bundler = new ParcelBundler("./index.js", {
outDir: "./dist",
watch: false,
logLevel: 1,
});
async function test(v) {
fs.writeFileSync("index.js", `module.exports = ${v};`);
await bundler.bundle();
}
(async function () {
await test(0);
console.log("bundle exports: ", require("./dist/index.js"));
delete require.cache[require.resolve("./dist/index.js")];
await test(1);
console.log("bundle exports: ", require("./dist/index.js"));
})();
The out put will be:
bundle exports: 0
bundle exports: 0
Now, with my hack:
const fs = require("fs");
const { resolve } = require("path");
const ParcelBundler = require("parcel-bundler");
const bundler = new ParcelBundler("./index.js", {
outDir: "./dist",
watch: false,
logLevel: 1,
});
async function test(v) {
fs.writeFileSync("./index.js", `module.exports = ${v};`);
if (v > 0) {
let asset = await bundler.resolveAsset(resolve("./index.js"));
await bundler.buildQueue.add(asset, true);
}
await bundler.bundle();
}
(async function () {
await test(0);
console.log("bundle exports: ", require("./dist/index.js"));
delete require.cache[require.resolve("./dist/index.js")];
await test(1);
console.log("bundle exports: ", require("./dist/index.js"));
})();
We get the expected result:
bundle exports: 0
bundle exports: 1
Also in your example, you re-build everything from scratch.
No, Parcel will determine which files changed, and internally requeue changed files
The out put will be:
bundle exports: 0
bundle exports: 0
That invoking build on a single Parcel instance multiple times doesn't work is a bug. I'm afraid you'll have to use your hack for now
I don't really understand, class Bundler in packages/core/parcel-bundler/src/Bundler.js is not singleton, also I can't see much see any singleton pattern to load the assets (after the code is big, I might miss something), e.g. this.loadedAssets = new Map(); in the constructor. So how can parcel keep history to determine if file(s) changed or not?
Also when I use new Bundler each build take 14 sec _(in my test for radka js)_, but when I use my hack, the first build get 14 sec and then the next builds take only 4 sec, that is a huge improvement...
That invoking build on a single Parcel instance multiple times doesn't work is a bug. I'm afraid you'll have to use your hack for now
Do you plan to fix this at some point?
Do you plan to fix this at some point?
For Parcel 2: yes https://github.com/parcel-bundler/parcel/pull/4290
Waoooo, parcel v2 seem very good and the caching system is impressive. Also seem that the issues I had in watch mode with the current version is solved in the v2, so I would not even need to use my own watcher.Since v2 is also much more configurable, maybe I can use all the power of parcel as main engine for my tool.
Therefor, I close the issue and hope we get this v2 soon to the final release ;-)