Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fails on Node shebang (#!/usr/bin/env node) #235

Closed
thibaudcolas opened this issue Oct 28, 2015 · 17 comments
Closed

Fails on Node shebang (#!/usr/bin/env node) #235

thibaudcolas opened this issue Oct 28, 2015 · 17 comments

Comments

@thibaudcolas
Copy link

I'm trying to use Rollup on a CLI, but it doesn't seem to like shebangs.

Here's a file that reproduces the issue:

#!/usr/bin/env node

console.log('Hello, World!');

I'm using rollup version 0.20.2. Not sure if you'll want to support this as this is not standard JS. Browserify does (by removing the line). Webpack doesn't. Babel does (by leaving the line as is).

@Victorystick
Copy link
Contributor

Since it isn't standard JS, I'm not sure what our official standpoint is. We could probably support it at some point in time.

If you want to make it work now, consider removing #!/usr/bin/env node from the source and adding it as a banner option.

@eventualbuddha
Copy link
Contributor

Personally, I've been supporting shebang lines in any tools I've written
recently since they are quite common in the *nix world. It'd be annoying
if, for example, source editors flagged them as invalid syntax even if #
isn't the comment character in whatever language you're writing in.

I'll submit a PR for this.

On Wed, Oct 28, 2015 at 4:25 AM Oskar Segersvärd notifications@github.com
wrote:

Since it isn't standard JS, I'm not sure what our official standpoint is.
We could probably support it at some point in time.

If you want to make it work now, consider removing #!/usr/bin/env node
from the source and adding it as a banner
https://github.com/rollup/rollup/wiki/JavaScript-API#bannerfooter
option.


Reply to this email directly or view it on GitHub
#235 (comment).

@eventualbuddha
Copy link
Contributor

Thinking about this a bit more after trying to build support for it as a plugin, I'm not sure it's possible to do yet. It should be done as a banner, as @Victorystick suggests, but plugins can't currently provide banners. Even if they could, it can't be a static value and needs to be based on the input. Currently the easiest way would be to provide the Bundle so the plugin could get entryModule and check its originalCode and graft any shebang found there as a banner in the rendered output. Passing the entire Bundle is probably leaking too much internal structure to plugins, though. Other thoughts on how to approach this?

@Rich-Harris
Copy link
Contributor

I'm probably missing something but why would the plugin need to know about the bundle or entry module in this case? Couldn't it just provide a banner function that returned #!/usr/bin/env node (or whatever option was provided)?

@thibaudcolas
Copy link
Author

My two cents: I didn't know about banner and it seems like a solid option. Going further than that (with or without a plugin) is probably a question of how much you want this to be a drop-in replacement for other tools used in the same scenario.

Here's what browserify did when this question came up: browserify/browserify#297 (tl;dr: they decided to support it since it is also supported by node itself).

@Rich-Harris
Copy link
Contributor

One good reason not to support it: when generating a CommonJS bundle (which is presumably what we're talking about), the shebang would appear below the 'use strict' pragma...

'use strict';

#!/usr/bin/env node

console.log('Hello, World!');

...and that assumes that there's only one module (if anything is imported, it will generally appear before the entry module).

The banner option is designed for exactly this sort of scenario, and I'm loath to add special case logic unless it adds missing functionality – these things have a habit of piling up :) So I'll close this but open an issue for that. We do presumably need to add a banner hook for plugins though. If necessary it would be fairly straightforward to create a plugin that strips out shebangs in source files.

@Rich-Harris
Copy link
Contributor

0.20.3 allows plugins to supply a banner/footer option

@hollowdoor
Copy link

I know this is old but for anyone interested you can do something like this:

const writeFile = require('fs').writeFile;
const rollup = require('rollup');

rollup.rollup({
    entry: 'source.js',
    acorn: {
         //Let the hashbang be
        allowHashBang: true
    }
}).then(bundle=>{
    let code = bundle.generate({
        format: 'cjs'
    }).code;

    let bangReg = /\n(#[!][^\n]+?\n)/;
    //remove the hashbang from somewhere below 'use strict';
    let hashBang = code.match(bangReg);
    if(hashBang){
        code = code.replace(bangReg, '');
        //put the hashbang where it belongs
        code = hashBang[1] + code;
    }

    writeFile('dist.js', code, (error)=>{
        throw error;
    });
})

This would be just for executable files you create yourself. It might break something else.

@vjeux
Copy link

vjeux commented May 29, 2017

Here's a workaround you can use from within the config only:

import replace from 'rollup-plugin-replace';

export default {
  banner: '#!/usr/bin/env node',
  plugins: [
    replace({
      '#!/usr/bin/env node': ''
    }),
  // ...

This will remove the shebang before feeding it to rollup plugins and then put it back at the end.

@paulocoghi
Copy link

paulocoghi commented Apr 26, 2018

@vjeux Does this solution still work for you? I've tried here but the problem persist.

I am using rollup-plugin-commonjs and rollup-plugin-node-resolve, and I tried your solution, testing replace both before and after them, without success.

@shaunwallace
Copy link

@paulocoghi if you use the delimiter option it should resolve your issue.

import replace from 'rollup-plugin-replace';

export default {
  banner: '#!/usr/bin/env node',
  plugins: [
    replace({
     delimiters: ['', ''],
      '#!/usr/bin/env node': ''
    }),
  // ...

The above was tested with:

  • "rollup": "^0.62.0",
  • "rollup-plugin-replace": "^2.0.0"

@stubar
Copy link

stubar commented Feb 8, 2019

Has anyone had success in using https://github.com/developit/rollup-plugin-preserve-shebang, from what I can see it will only do stuff if it finds a shebang in the source, but shebang in the source breaks rollup and I get a

[!] Error: Unexpected character '#' (Note that you need plugins to import files that are not JavaScript)

Seems like the banner approach is the way to go.

@manferlo81
Copy link

manferlo81 commented Mar 20, 2019

I noticed this issue is closed, I had the same problem and I ended up writing a plugin myself, I published it under rollup-plugin-strip-shebang in case someone is interested.

@elado
Copy link

elado commented Oct 23, 2019

just published a package that preserves shebangs - reads what shebangs are in the files, strips them so rollup can continue compiling, and then brings them back in the output file.

https://github.com/elado/rollup-plugin-preserve-shebangs
https://www.npmjs.com/package/rollup-plugin-preserve-shebangs

@wbcs
Copy link

wbcs commented Dec 26, 2019

just published a package that preserves shebangs - reads what shebangs are in the files, strips them so rollup can continue compiling, and then brings them back in the output file.

https://github.com/elado/rollup-plugin-preserve-shebangs
https://www.npmjs.com/package/rollup-plugin-preserve-shebangs

Thank you, that works for me😆

@kiprasmel
Copy link

kiprasmel commented Jan 18, 2020

hasparus added a commit to hasparus/microbundle that referenced this issue Mar 15, 2020
hasparus added a commit to hasparus/microbundle that referenced this issue Mar 15, 2020
@jacksteamdev
Copy link
Contributor

It's probably simplest to use output.banner, no plugins to install and configure.

  output: {
    file: 'bin/migrate.js',
    banner: '#!/usr/bin/env node',
  },

The rollup-plugin-preserve-shebangs didn't work for me, it just stripped the shebang. 😞

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests