Parcel: [RFC] CLI flag to specify action to run after bundling finishes

Created on 13 Feb 2018  Ā·  14Comments  Ā·  Source: parcel-bundler/parcel

As @microcipcip pointed out, Parcel doesn’t have any easy way to run a script after bundling finishes. So if you want to call some script that further processes the bundled files after they get bundled, there’s no easy way to do that from the CLI if you are running parcel in watch mode.

Implementation seems pretty straightforward but I wanted to get some feedback from the community before going ahead and implementing it.

Some Questions / Discussion Points

  • What should we call the CLI flag?

    1. --postbundle?

    2. --then?



      • This actually looks pretty nice: parcel entry.abc --then script.js but might not be intuitive to everyone



    3. Anything else

  • What should the command take as its input? Should it take a file name of a node script to execute, or should it take any arbitrary string containing some bash commands?

    1. parcel entry.abc -x script.js

    2. parcel entry.abc -x ā€˜node script.js’



      • Which allows you to use any command, like: parcel entry.abc -x ā€˜python somescript.py’



So ya, would love to get feedback from you guys on what you think about this and any thoughts you guys have on the things above.

Feature RFC

Most helpful comment

Just FYI.

I've been developing a server with Node and Typescript, and I needed to re-build the app and restart it on every file change.

That's how I got here.

Anyway, I've solved it with Nodemon. Here's how:

nodemon --exec 'parcel build src/server.ts --bundle-node-modules && node dist/server.js' -e ts --watch src

In other words, Nodemon watches src/ for changes in ts files and runs a specified command on each change.

All 14 comments

Does the script need a reference to current bundle/bundler, as currently with bundler.on('bundled', (bundle)=>{})?
The node/python distinction could be solved with a shebang in the script and always invoking ./script.[ext]. (Maybe only if the extension isn't js.)

@mischnic

  • ā€œDoes the script need a reference to current bundle/bundler, as currently with bundler.on(ā€˜bundled’, (bundle)=>{})?"

    • That would be really cool but I’m pretty sure that’s physically impossible (unless there’s some way to share memory with other node processes). What we can do though is pass in a string with the path to the bundled file.

  • "The node/python distinction could be solved with a shebang in the script and always invoking ./script.[ext]. (Maybe only if the extension isn’t js.)ā€

    • I like this šŸ‘ So we can detect if the input has a .js file extension and run it as a child process in those cases, and if not then we execute it as an executable.

That would be really cool but I’m pretty sure that’s physically impossible (unless there’s some way to share memory with other node processes).

So we can detect if the input has a .js file extension and run it as a child process in those cases, and if not then we execute it as an executable.

With a javascript file, parameters could be passed as it is currently the case with plugins (along the lines of require(...file...)(bundle) and with module.export = function(bundle){...}, but that should be optional).
But my main point was that Javascript files can be ran in the current node process (like plugins) and the shebang isn't needed (less complexity).

What should we call the CLI flag?

--postbundle seems self-explanatory

What should the command take as its input? Should it take a file name of a node script to execute, or should it take any arbitrary string containing some bash commands?

I'd say a string so to give maximum flexibility

I'm not sure if this should be a feature?
This seems like an advanced use-case that can be perfectly achieved by using the parcel api instead of the cli, as you're already writing a script for post processing why not initiate and execute the parcel bundler through the api instead? Seems more straightforward and would also add the ability to have access to the entire bundler object, which adds info that might be usefull (for example bundlenames and the assets it contains)

In agreement with @DeMoorJasper here. The API gives you the flexibility to tap into the buildEnd event. If you're doing a single build, this will fire once. If you're using the dev server or watch, it will fire every time a build completes:

// setup Bundler
const bundler = new Bundler(main, command);

// attach events
bundler.on('buildEnd', () => {
  // run post-build scripts
})

bundler.bundle(); // or bundler.serve();

Seems reasonable to use the API for this I think. We should probably document it so people know they can do that though! :)

Also, this won't work for development, but for build scripts you can just chain the commands: parcel build index.html && ./my_script.sh

Curious what your usecase is for this though. Can you provide some context?

@devongovett I am including the dist files in a php CMS and I need to add manually a versioning string that reads from a file. I generate a file called dist/.version where there is basically just a timestamp. I need to generate it at every dev build and during watch so that when I upload my site it will refresh the entry point in my heavily cached server.

@brandon93s code snippet seems ok but I do agree that this should be documented.

The events of the bundler should really be documented. What is the difference between 'bundled' and 'buildEnd' ?

The bundled event fires on successful bundle and will emit the bundle object. If bundling fails, it will not fire.

buildEnd will always fire at the end of a bundle run, regardless of whether errors occurred or not. It does not emit any data.

Looks like we have consensus... there’s no real need for this feature at this point.

Sorry @microcipcip but I’m gonna close this issue, but let us know if you need help accomplishing this using the Bundler class.

Just FYI.

I've been developing a server with Node and Typescript, and I needed to re-build the app and restart it on every file change.

That's how I got here.

Anyway, I've solved it with Nodemon. Here's how:

nodemon --exec 'parcel build src/server.ts --bundle-node-modules && node dist/server.js' -e ts --watch src

In other words, Nodemon watches src/ for changes in ts files and runs a specified command on each change.

I've been developing a server with Node and Typescript, and I needed to re-build the app and restart it on every file change.

The proper solution for this is described in #935

The proper solution for this is described in #935

Not implemented though. :)

I might want to work on #935 in future if nobody takes it first.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

adamreisnz picture adamreisnz  Ā·  3Comments

Niggler picture Niggler  Ā·  3Comments

dsky1990 picture dsky1990  Ā·  3Comments

philipodev picture philipodev  Ā·  3Comments

mnn picture mnn  Ā·  3Comments