149

I want to try using npm to run my various build tasks for a web application. I know I can do this by adding a scripts field to my package.json like so:

"scripts": {
   "build": "some build command"
},

This gets unwieldy when you have more complex commands with a bunch of options. Is it possible to move these commands to a bash script or something along those lines? Something like:

"scripts": {
   "build": "build.sh"
},

where npm run build would execute the commands in the build.sh file?

Reading through this post it seems like it is, but I'm not clear on exactly where I'm supposed to drop my build.sh file or if I'm missing something.

8
  • 36
    Don't do this. Node runs everywhere. Bash does not. Whatever you're doing in bash you can do in node, and even CLI invocation can be done using package dependencies. Need rm? install rimraf, then use that in an npm script. mkdir -p? install mkdirp and then use that in an npm script. You have a platform independent universal scripting language, right there, don't then go and pretend it 'Nix only. Does the commandline get too complicated? Use a task runner like grunt or gulp. Keep it universal. Commented Jan 22, 2016 at 2:05
  • 26
    The comments above say no, for a good reason, portability. But it depends on your audience. If it's an internal project, if your developers are on UNIX like variants (Linux/Macs etc) it is perfectly fine. If you're creating a general purpose library it is probably not... There is distinct benefits to using BASH/SH, you will be able to achieve some things in one line that will need pages of Grunt/Gulp, but then, you're probably excluding Windows users, which may, or may not be a problem. Commented Oct 20, 2017 at 6:52
  • 4
    Why is rimraf better than rm -rf for a web application? rimraf has to do things one file at a time, and just more packages you don't need. If a web server doesn't have bash then you can use del, but it likely has bash if the user is developing with node anyway and not .net or something. Even if it is .net it still probably has some form of gitbash or something. Commented Nov 17, 2019 at 9:50
  • 7
    @Mike'Pomax'Kamermans The reasoning that every Node application must be portable just because Node is is simply incorrect. Commented Mar 3, 2020 at 15:13
  • 2
    There are lots of reasons to use familiar tools rather than invest time and energy meeting a portability requirement which doesn't necessarily exist in the given project. Commented Mar 6, 2021 at 11:23

6 Answers 6

228

Its totally possible...

"scripts": {
   "build": "./build.sh"
},

also, make sure you put a hash bang at the top of your bash file #!/usr/bin/env bash

also make sure you have permissions to execute the file

chmod +x ./build.sh

Finally, the command to run build in npm would be

npm run build
Sign up to request clarification or add additional context in comments.

13 Comments

you can put it wherever you want just make sure you put the relative path in package.json eg "build": ". ./path/to/my/awesome/build/file/build.sh"
it runs the script in the current shell superuser.com/questions/46139/what-does-source-do
What about windows?
On Windows gitbash: '.' is not recognized as an internal or external command, operable program or batch file. See here for details explaining why. Additionally, setting sh files to be opened up with gitbash by default or any other environment that can run bash scripts will get this to work.
In windows bash following npm script worked for me: "name": "bash ./name.sh"
|
41

If you don't want to bother with giving permissions and the env you execute the script has for example sh, you could just do

"scripts": {
   "build": "sh ./build.sh"
}

1 Comment

Note that this could invoke a strictly POSIX shell (stackoverflow.com/questions/5725296/…), which these days often is not found anymore in shell scripts.
9

Even Simpler:

I routinely do this for one-offs and PoC's not involving a VCS

package.json
{
    "scripts": {
        "ship": "rsync -avz deployable/* <some-server>:/var/www/some-site/sub-dir/"
    },
}
...

Comments

5
  • Just add 'bash' keyword before the file_name.sh

    "scripts": { "build": "bash ./file_name.sh" }

  • then run "npm run build" on terminal

2 Comments

What is the benefit of adding the bash keyword?
With that you explicitly tell it to use the bash terminal to execute the command. This way your executable doesn't need permissions to be executable, because bash already handles this.
1

In case someone sees this and is using Docker for creating an image of this application.

Regarding:

but I'm not clear on exactly where I'm supposed to drop my build.sh file

Wherever you do decide to drop your build.sh file, make sure it is included in the Dockerfile image output, i.e. the file's path is in one of the COPY commands in the Dockerfile.

For example, if you have something like

scripts {
  "build": "./scripts/build.sh"
}

Then your Dockerfile should have a COPY command similar to:

COPY scripts/build.sh scripts/

Comments

0

In Windows 11 with Git bash, if you wish to run a set of commands (and not a script file), then bash -c is needed. Note how the chain of commands is within a double quote.

  "scripts": {
    "build": "bash -c \"export NODE_OPTIONS=--openssl-legacy-provider && ng build --base-href /example/ --prod --output-path example\"",
  },

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.