Generating sourcemaps with npm scripts using node-sass and postcss autoprefixer - npm

Is it possible to generate fully working sourcemaps using node-sass and postcss autoprefixer when piping output from one to another? I currently have the following in package.json:
"scripts": {
"sass": "node-sass sass/app.scss --source-map true --source-map-embed true",
"postcss:autoprefixer": "postcss --use autoprefixer -b 'last 2 versions' --map",
"css": "npm run sass -s | npm run postcss:autoprefixer -s > css/app.css"
}
This produces a semi-working inline sourcemap, but the links to original files are incorrect, so clicking on them in Chrome devtools won't load them (it seems like they are processed as relative links and then referenced from the css folder). I tried to fix this by adding the --source-map-contents true option to node-sass, but then autoprefixer bugs out, I suspect because it doesn't like the line length of the dataUri.
Ideally I'd prefer to output a separate .map file anyway, but setting the node-sass option to --source-map css/app.css.map doesn't write anything out, presumably because only the css is output to stdout.

Replacing source-map with source-map-root and a filesystem URL seems to do the trick:
"scripts": {
"sass": "node-sass sass/app.scss --source-map-root file://${PWD}/ --source-map-embed true",
"postcss:autoprefixer": "postcss --use autoprefixer -b 'last 2 versions' --map",
"css": "npm run sass -s | npm run postcss:autoprefixer -s > css/app.css"
}
Would still be good to know if it was possible to output separate .map files though!
Update:
Below is the new package.json using exorcist as recommended by RyanZim's comment:
"scripts": {
"sass": "node-sass sass/app.scss --source-map-root file://${PWD}/ --source-map-embed true",
"postcss:autoprefixer": "postcss --use autoprefixer -b 'last 2 versions' --map",
"css": "npm run sass -s | npm run postcss:autoprefixer -s | exorcist css/app.css.map > css/app.css"
}

Try:
sass input.scss:output.css

Related

double commande in package.json don't work

I have an app where I would like to compile all my handlebars template/partials
The command I execute is (npx cause is a local package) =>
Build Views
npx handlebars ./public/templates/views -f ./public/templates/view.js --extension 'hbs'
Build Template
npx handlebars ./public/templates/partials -f ./public/templates/partials.js --extension 'hbs'
It work if I run them independently
now, I tried to combine them,
"scripts": {
"hbs": "npx handlebars ./public/templates/views -f ./public/templates/view.js --extension 'hbs' && npx handlebars ./public/templates/partials -f ./public/templates/partials.js --extension 'hbs'",
},
but the command do not run, instead, I get prompted with the library !help like if the command is invalid.
Is there something I miss ?
Per comments on question, the single quotes are being incorrectly included into the --extension option for handlebars. The suggested format for the script is:
"scripts": {
"hbs": "handlebars ./public/templates/views -f ./public/templates/view.js --extension hbs && handlebars ./public/templates/partials -f ./public/templates/partials.js --extension hbs",
},

Adding a delay to npm's concurrently

I am using NPM's concurrently to run:
concurrently "npm run watch-sass" "npm run watch"
"scripts": {
"test": "nps test",
"watch-sass": "multi-sass -w -d static/css/pages -o static/css/pages -n -d static/css/common -o static/css/common -n -d static/css/components -o static/css/components",
"watch": "nps webpack.build.development.watch",
...
},
However, as soon as watch-sass completes a single file, watch runs and the files do not have a chance to be included in the build.
I need to insert some kind of delay after 'watch-sass' so that 'watch' will not activate until either (1) a delay everytime, or (2) a way to know when ALL scss files have been compiled.

How to avoid subdirectory output in node-sass?

I have following setup under my project:
/assets/scss has many SCSS files organized under different subdirectories; including a root global.scss file. As you can imagine, global.scss will only have #imports.
/assets/css is set as output directory. I am trying to output only one file under this folder - global.css.
package.json has this command
"scripts": {
"scss": "node-sass --watch assets/scss/styleguide.scss -o assets/css --recursive"
}
When I run npm run scss it outputs subdirectory CSS files as well. Does anyone know how to avoid output of subdirectory sass files?
Thanks in advance!
You are passing the --recursive argument to node-sass. That will mean that node-sass will search recursively on every directory under assets/scss and will compile all the scss files found. To avoid that behavior just remove the --recursive option:
"scripts": {
"scss": "node-sass --watch assets/scss/styleguide.scss -o assets/css"
}
More about node-sass usages and options can be found here.

npm seems to be messing up my shell script which invokes uglifyjs

I have webpack use babel to transpile es6 files into es5. I want to compress these using uglifyjs. The method I used which worked till today was to have this script file be invoked with npm:
scripts/uglifyjs:
#!/usr/bin/env zsh
for file in ./public/assets/js/*.js
do
echo "uglifying `basename $file`"
uglifyjs --verbose --compress --source-map content=${file:2}.map,url=`basename $file`.map,filename=${file:2}.map,includeSources=true --output $file $file
done
And in my package.json:
"scripts": {
...
"uglifyjs": "scripts/uglifyjs",
Take the first file that gets invoked, links.js. If I manually type the command is works:
$ uglifyjs --verbose --compress --source-map content=public/assets/js/links.js.map,url=links.js.map,filename=public/assets/js/links.js.map,includeSources=true --output ./public/assets/js/links.js ./public/assets/js/links.js
INFO: Using input source map: public/assets/js/links.js.map
When running npm run uglifyjs I get the following error:
$ npm run uglifyjs
> jbuk-frontend#0.0.1 uglifyjs /home/jonny/git/jonnybarnes.uk
> scripts/uglifyjs
uglifying links.js
fs.js:651
return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
^
Error: ENOENT: no such file or directory, open 'content=public/assets/js/links.js.map,url=links.js.map,filename=public/assets/js/links.js.map,includeSources=true'
at Object.fs.openSync (fs.js:651:18)
at Object.fs.writeFileSync (fs.js:1300:33)
at done (/home/jonny/git/jonnybarnes.uk/node_modules/uglify-js/bin/uglifyjs:516:20)
at cb (/home/jonny/git/jonnybarnes.uk/node_modules/uglify-js/bin/uglifyjs:324:39)
at /home/jonny/git/jonnybarnes.uk/node_modules/uglify-js/bin/uglifyjs:391:9
at tryToString (fs.js:512:3)
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:500:12)
I don’t know why I can run the command manually, but not via npm, it worked before. Is this a known change with npm v5?

Unable to read parameters from package.json

I am unable to read parameters from package.json, so it's always $(directory).
and this is my command:
npm run migrate -- -directory "migration_dir"
package.json
{
"name": "XXXX",
"version": "0.1.0",
"description": "XXX",
"main": "app.js",
"scripts": {
"migrate": "cd $(directory)"
},
"keywords": [
"XXXX"
],
"author": "XXXX",
"license": "MIT"
}
Thank you.
The problem you may be facing is two-fold.
1. Arguments syntax for run-script
From npm docs:
As of npm#2.0.0, you can use custom arguments when executing scripts. The special option -- is used by getopt to delimit the end of the options. npm will pass all the arguments after the -- directly to your script:
npm run test -- --grep="pattern"
Arguments after -- will be passed directly, in your case that is
$ cd $(directory) -directory "migration_dir"
To fix that, you have to change your script definition accordingly:
"scripts": {
"migrate": "cd"
}
And pass the directory with no -directory option:
$ npm run migrate -- "migration_dir"
This will execute
$ cd "migration_dir"
2. Scripts are executing in a subshell
The migrate script you posted is useless because all npm scripts are executed in subshells, and changing the working directory from inside a subshell doesn't make a difference when a subshell exits.
Although if your script does anything beyond cd that will work:
"scripts": {
"foo": "cd / && pwd"
}
Part of the script after && will see the effect of cd, but your shell won't.
$ npm run foo
> cd / && pwd
/
$ pwd
/your/original/path
However, you can't specify additional arguments using -- anymore (npm run foo -- arg will do cd / && pwd arg).
It's look like You want to read a ENV parameter. Bash notation is ${directory} not $(directory).
Now You can run migration
directory="migration_dir" npm run migrate
The output is
cd migration_dir
Pros of this solution is possibility of use complicated scripts.