Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read from config file in scripts section in package.json

Is there a possibility to read from a config file within the "scripts" section in package.json?

Background of the question: We are several developers who all work on the same terminal server. And we have a the following section in our package.json

...
"scripts": {
    "serve": "vue-cli-service serve --port 8080"
}
...

Since we are on the same server we need a way to specify a different port. One possibility is to use a command line parameter. But i would appreciate an "easier" way where i can store a port in a config file which i add to .gitignore, so that every developer can have his own file and we can just type npm run serve without thinking about to enter a port.

Maybe there is a better way of doing what i want. I am open to suggestions.

like image 904
VSDekar Avatar asked Dec 15 '25 03:12

VSDekar


1 Answers

One possibility is to use a command line parameter.

Yes, for that you'll need to configure your serve script in package.json like this:

"scripts": {
  "serve": "vue-cli-service serve --port"
}

Then via you CLI tool run:

npm run serve -- <port_number>

Note: the <port_number> argument should replaced with a real port number, e.g. 8080, 3000 etc ...


...I would appreciate an "easier" way where I can store a port in a config file ...

The config file:

Let's say we have a file arbitrarily named .portnumber which is saved in the root of the project directory. For example:

.
├── .gitignore
├── .portnumber    <------ 
├── node_modules
│   └── ...
├── package.json
└── ...

and the contents of the .portnumber file contains the port number to be used only. For example:

3000

Solution A: *Nix platforms only (Linux/MacOS...)

When running npm scripts on *nix platforms the default shell that npm utilizes is sh. Therefore the following will work.

package.json

"scripts": {
  "serve": "vue-cli-service serve --port \"$(<.portnumber)\""
}

The $(<.portnumber) part above essentially reads the contents of the .portnumber file, (that's what the <.portnumber part does), and utilizes command Substitution.

So given that the .portnumber file contains 3000 the command being executed in the npm script is effectively:

vue-cli-service serve --port 3000

You could also do this:

package.json

"scripts": {
  "serve-with-default": "port=$(<.portnumber); vue-cli-service serve --port \"${port:-8080}\""
}

This is very similar to the previous, however if the .portnumber file did not exist or was empty, it would default to using 8080 for the port number.


Solution B: Cross Platform (Windows/Linux/macOS...)

For a cross platform solution, (i.e. one that runs successfully on Windows, Linux, and macOS...), you'll need to utilize nodejs to achieve your requirement. There are a couple of different ways to approach this as described in the following two sub-sections titled:

  • Using an external nodejs (.js) file
  • Inlining your JavaScript in package.json.

Using an external nodejs (.js) file

Create a file named serve.js

serve.js

const readFileSync = require('fs').readFileSync;
const execSync = require('child_process').execSync;

const port = readFileSync('.portnumber', {encoding: 'utf8'});

execSync('vue-cli-service serve --port ' + port, {stdio: 'inherit'})

.. and also save it in your project directory:

.
├── .gitignore
├── .portnumber    <------ 
├── node_modules
│   └── ...
├── package.json
├── serve.js       <------ 
└── ...

Redefine your serve npm script as follows:

package.json

"scripts": {
  "serve": "node serve"
}

Explanation:

The serve.js file essentially does the following:

  • Utilizes the node.js built-in readFileSync to read the contents of the .portnumber file and assigns the number to the port variable.

  • Then utilizes the node.js built-in execSync to run the vue-cli-service serve --port command with the port number that was previously read from the .portnumber file.

Inlining your JavaScript in package.json.

Alternatively, you can inline your nodejs/JavaScript code in the scripts section of your package.json instead. In which case redefine your npm script as follows:

package.json

"scripts": {
  "serve" : "node -e \"require('child_process').execSync('vue-cli-service serve --port ' + require('fs').readFileSync('.portnumber', {encoding: 'utf8'}), {stdio: 'inherit'})\""
}

Explanation:

  • This is effectively the same, (albeit refactored), as the aforementioned solution that utilized a separate .js file, however the use of a separate nodejs script/file is now redundant.
  • The nodejs command line option -e is utilized to evaluate the inline JavaScript.
like image 161
RobC Avatar answered Dec 16 '25 21:12

RobC