├── .gitignore ├── LICENSE ├── README.md ├── assets ├── markup │ └── index.jade ├── scripts │ ├── main.js │ ├── text.js │ └── write.js └── styles │ ├── body.styl │ ├── headings.styl │ └── main.styl ├── dist ├── .gitkeep ├── main.css ├── main.css.map └── main5554549a.css ├── doBuild ├── doBuild.bat ├── karma.conf.js ├── package.json ├── test └── write.test.js └── tips ├── README.md ├── add-text-banner-to-output-file.md ├── find-and-destroy-running-script.md ├── live-reload-with-node+express.md ├── run-commands-when-files-change.md └── use-javascript-in-package-file.md /.gitignore: -------------------------------------------------------------------------------- 1 | dist/* 2 | assets.json 3 | /node_modules 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) Copyright © 2014 Keith Cirkel, http://keithcirkel.co.uk 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the “Software”), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NPM Scripts Example 2 | 3 | 4 | 5 | Firstly, you should go and read [how to use NPM as a build tool][post]. Then 6 | come back here and explore the repository. It's fairly standard, and the bare 7 | minimum to show you what a complex config would look like. 8 | 9 | ## Contributing 10 | 11 | See some areas for optimising? Great! Send a PR, I'm definitely interested in 12 | seeing some great ways to optimise this. 13 | 14 | ## Notes 15 | 16 | Several scripts use the `npm` `-s` flag to silence `npm`'s output from the subtasks, which makes the log output a little tidier (it is a shortcut for --loglevel=silent, read more on npms documentation for flags: https://docs.npmjs.com/misc/config#default-configs). 17 | 18 | [post]: https://www.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/ 19 | 20 | ## Tips and tricks 21 | 22 | Some issues were created in order to discuss or share solutions for additional situations. 23 | 24 | These tips and tricks will be documented inside the [`/tips`](tips) folder inside their own `.md` files. 25 | -------------------------------------------------------------------------------- /assets/markup/index.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html(lang="en") 3 | head 4 | title NPM Scripts Demo 5 | script(src="#{locals['dist/main.js'].substr(5)}") 6 | if compileDebug 7 | script(src="//localhost:9091/livereload.js") 8 | 9 | link(rel="stylesheet",href="#{locals['dist/main.css'].substr(5)}") 10 | body 11 | h1 npm scripts demo 12 | #container 13 | p. 14 | All of this content was created using various preprocessors and 15 | compilers, as well as test tools and watchers, without using 16 | Grunt, Gulp, Brocolli, Fez, Jake, etc. 17 | -------------------------------------------------------------------------------- /assets/scripts/main.js: -------------------------------------------------------------------------------- 1 | var write = require('./write'); 2 | window.addEventListener('DOMContentLoaded', write); 3 | -------------------------------------------------------------------------------- /assets/scripts/text.js: -------------------------------------------------------------------------------- 1 | module.exports = 'This text was loaded from the JS file!'; 2 | -------------------------------------------------------------------------------- /assets/scripts/write.js: -------------------------------------------------------------------------------- 1 | var text = require('./text'); 2 | module.exports = function () { 3 | var heading = document.createElement('h2'); 4 | heading.textContent = text; 5 | document.getElementById('container').appendChild(heading); 6 | }; 7 | -------------------------------------------------------------------------------- /assets/styles/body.styl: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | background: #c3bdb3; 5 | color: #334; 6 | font-family: sans-serif; 7 | } 8 | -------------------------------------------------------------------------------- /assets/styles/headings.styl: -------------------------------------------------------------------------------- 1 | h1 { 2 | display: block; 3 | text-align: center; 4 | font-size: 10vh; 5 | } 6 | -------------------------------------------------------------------------------- /assets/styles/main.styl: -------------------------------------------------------------------------------- 1 | @import 'body.styl' 2 | @import 'headings.styl' 3 | -------------------------------------------------------------------------------- /dist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keithamus/npm-scripts-example/56c25ca38f96779d9bcddedf9ebcbd95d70df05a/dist/.gitkeep -------------------------------------------------------------------------------- /dist/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | background: #c3bdb3; 5 | color: #334; 6 | font-family: sans-serif; 7 | } 8 | h1 { 9 | display: block; 10 | text-align: center; 11 | font-size: 10vh; 12 | } 13 | /*# sourceMappingURL=main.css.map */ -------------------------------------------------------------------------------- /dist/main.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["../assets/styles/body.styl","../assets/styles/headings.styl"],"names":[],"mappings":"AAAA;EACI,QAAQ,EAAR;EACA,SAAS,EAAT;EACA,YAAY,QAAZ;EACA,OAAO,KAAP;EACA,aAAa,WAAb;;ACLJ;EACI,SAAS,MAAT;EACA,YAAY,OAAZ;EACA,WAAW,KAAX","file":"main.css"} -------------------------------------------------------------------------------- /dist/main5554549a.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | background: #c3bdb3; 5 | color: #334; 6 | font-family: sans-serif; 7 | } 8 | h1 { 9 | display: block; 10 | text-align: center; 11 | font-size: 10vh; 12 | } 13 | /*# sourceMappingURL=main.css.map */ -------------------------------------------------------------------------------- /doBuild: -------------------------------------------------------------------------------- 1 | npm run build -------------------------------------------------------------------------------- /doBuild.bat: -------------------------------------------------------------------------------- 1 | npm run build -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Tue Dec 09 2014 00:00:12 GMT+0000 (GMT) 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | 7 | // base path that will be used to resolve all patterns (eg. files, exclude) 8 | basePath: '', 9 | 10 | 11 | // frameworks to use 12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 13 | frameworks: ['browserify', 'mocha'], 14 | 15 | 16 | // list of files / patterns to load in the browser 17 | files: [ 18 | 'test/**.js' 19 | ], 20 | 21 | 22 | // list of files to exclude 23 | exclude: [ 24 | ], 25 | 26 | 27 | // preprocess matching files before serving them to the browser 28 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 29 | preprocessors: { 30 | 'test/**.js': ['browserify'] 31 | }, 32 | 33 | browserify: { 34 | debug: true, 35 | }, 36 | 37 | 38 | // test results reporter to use 39 | // possible values: 'dots', 'progress' 40 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 41 | reporters: ['progress'], 42 | 43 | 44 | // web server port 45 | port: 9876, 46 | 47 | 48 | // enable / disable colors in the output (reporters and logs) 49 | colors: true, 50 | 51 | 52 | // level of logging 53 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 54 | logLevel: config.LOG_WARN, 55 | 56 | 57 | // enable / disable watching file and executing tests whenever any file changes 58 | autoWatch: true, 59 | 60 | 61 | // start these browsers 62 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 63 | browsers: ['PhantomJS'], 64 | 65 | 66 | // Continuous Integration mode 67 | // if true, Karma captures browsers, runs the tests and exits 68 | singleRun: false 69 | }); 70 | }; 71 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "npm-scripts-example", 3 | "version": "1.0.0", 4 | "description": "An example of how to use npm scripts over a build tool like Grunt or Gulp", 5 | "main": "index.js", 6 | "author": "Keith Cirkel (http://keithcirkel.co.uk/)", 7 | "license": "MIT", 8 | "devDependencies": { 9 | "browserify": "^13.1.0", 10 | "hashmark": "^2.0.0", 11 | "http-server": "^0.7.3", 12 | "jade": "^1.7.0", 13 | "jshint": "^2.5.10", 14 | "karma": "^0.12.28", 15 | "karma-browserify": "^1.0.0", 16 | "karma-cli": "^0.0.4", 17 | "karma-mocha": "^0.1.10", 18 | "karma-phantomjs-launcher": "^1.0.2", 19 | "live-reload": "^1.1.0", 20 | "minifyify": "^6.0.0", 21 | "mocha": "^2.0.1", 22 | "nodemon": "^1.17.1", 23 | "npm-run-all": "^4.1.2", 24 | "opener": "^1.4.0", 25 | "rimraf": "^2.2.8", 26 | "s3-cli": "^0.11.1", 27 | "stylus": "^0.49.3", 28 | "wait-on": "^2.1.0" 29 | }, 30 | "repository": { 31 | "type": "git", 32 | "url": "git://github.com/keithamus/npm-scripts-example.git" 33 | }, 34 | "scripts": { 35 | "clean": "rimraf dist/*", 36 | "prebuild": "npm run clean -s", 37 | "build": "npm run build:scripts -s && npm run build:styles -s && npm run build:markup -s", 38 | "build:scripts": "browserify -d assets/scripts/main.js -p [minifyify --compressPath . --map main.js.map --output dist/main.js.map] | hashmark -n dist/main.js -s -l 8 -m assets.json \"dist/{name}{hash}{ext}\"", 39 | "build:styles": "stylus assets/styles/main.styl -m -o dist/ && hashmark -s -l 8 -m assets.json dist/main.css \"dist/{name}{hash}{ext}\"", 40 | "build:markup": "jade assets/markup/index.jade --obj assets.json -o dist", 41 | "test": "karma start --singleRun", 42 | "watch": "npm-run-all --parallel \"watch:* -s\"", 43 | "watch:test": "karma start", 44 | "watch:build": "nodemon -q -w assets/ --ext \".\" --exec \"npm run build\"", 45 | "open:prod": "opener http://example.com", 46 | "open:stage": "opener http://staging.example.internal", 47 | "open:dev": "wait-on http://localhost:9090 && opener http://localhost:9090", 48 | "deploy:prod": "s3-cli sync ./dist/ s3://example-com/prod-site/", 49 | "deploy:stage": "s3-cli sync ./dist/ s3://example-com/stage-site/", 50 | "serve": "http-server -p 9090 dist/", 51 | "live-reload": "live-reload --port=9091 --delay=2000 dist/", 52 | "dev": "npm-run-all --parallel \"live-reload -s\" \"serve -s\" \"watch -s\" \"open:dev -s\"" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /test/write.test.js: -------------------------------------------------------------------------------- 1 | var write = require('../assets/scripts/write'); 2 | var text = require('../assets/scripts/text'); 3 | var assert = require('assert'); 4 | 5 | describe('write', function () { 6 | var div; 7 | 8 | beforeEach(function () { 9 | div = document.createElement('div'); 10 | div.id = 'container'; 11 | document.body.appendChild(div); 12 | }); 13 | 14 | afterEach(function () { 15 | div.parentElement.removeChild(div); 16 | }); 17 | 18 | it('Adds an h2 to container', function () { 19 | write(); 20 | var el = div.querySelector('h2'); 21 | assert(el, 'el exists'); 22 | }); 23 | 24 | it('Sets text to text.js module', function () { 25 | write(); 26 | var el = div.querySelector('h2'); 27 | assert(el.textContent === text, 'el text is ' + text); 28 | }); 29 | 30 | }); 31 | -------------------------------------------------------------------------------- /tips/README.md: -------------------------------------------------------------------------------- 1 | # Tips and tricks 2 | 3 | 4 | 5 | This folder should contain one `.md` file per tip with code snippets, details and instructions. -------------------------------------------------------------------------------- /tips/add-text-banner-to-output-file.md: -------------------------------------------------------------------------------- 1 | # Add text banner to output file 2 | 3 | ## Notes 4 | 5 | This tip was written via an [issue by @koskh on 18 Oct 2015](https://github.com/keithamus/npm-scripts-example/issues/31). 6 | 7 | ## Instructions 8 | 9 | If you want to add banner to output file, you could reproduce the following steps. 10 | 11 | 1. Make a helper file (`add-banner.js` for example) 12 | ```javascript 13 | var pckgJson = require(process.env.PWD +'/package.json'); 14 | var banner = '/* ' + pckgJson.name + ' - '+ pckgJson.config.banner +' - ' + new Date() + ' */\n'; 15 | 16 | process.stdout.write(banner); 17 | process.stdin.pipe(process.stdout); 18 | ``` 19 | 2. Add the data inside the `config` of `package.json` 20 | ```javascript 21 | "config": { 22 | "banner": " ...Header banner text ... " 23 | } 24 | ``` 25 | 3. Add into scripts for `node-sass`, `stylus` or whatever... 26 | ```javascript 27 | "build:sass": "node-sass ./style/index.scss | node ./utils/build/add-banner.js > ./build/index.css", 28 | "build:stylus": "stylus assets/styles/main.styl --print | node ./add-banner.js > dist/main.css", 29 | ``` 30 | 31 | ## Demo available on its dedicated branch 32 | 33 | This tips has been implemented on its own branch `tips/add-text-banner-to-output-file` (based on the master). 34 | 35 | Once you are on the branch, do `npm install` if necessary, then `npm run build:banner` which will run `stylus assets/styles/main.styl --print | node ./add-banner.js > dist/main.css` ... -------------------------------------------------------------------------------- /tips/find-and-destroy-running-script.md: -------------------------------------------------------------------------------- 1 | # Find and destroy running script 2 | 3 | ## Notes 4 | 5 | I wrote this while using Mac OS Sierra, I believe that commands might not work on Windows (it may work on Linux). 6 | 7 | Feel free to propose pull requests if you want to contribute to this documentation! 8 | 9 | ## Instructions 10 | 11 | If you happen to get an error concerning a port which is already taken by a running process and that you did not get this error the first time you launched the script, chances are that the script is still running in the background and still using its chosen port... 12 | 13 | ### Find if the port is still being used 14 | 15 | You can show all the network statistics using the command `netstat` in your Terminal: 16 | 17 | ``` 18 | $ netstat -vanp tcp 19 | 20 | Active Internet connections (including servers) 21 | Proto Recv-Q Send-Q Local Address Foreign Address (state) rhiwat shiwat pid epid 22 | tcp4 0 0 127.0.0.1.12443 127.0.0.1.64412 ESTABLISHED 405801 146988 335 0 23 | tcp4 0 0 127.0.0.1.54905 *.* LISTEN 131072 131072 46725 0 24 | tcp4 0 0 10.0.38.33.49695 54.77.194.154.443 TIME_WAIT 131072 131768 46723 0 25 | 26 | (...) 27 | ``` 28 | 29 | You will probably get a very long list and the easiest way to filter this out is to pipe your last command with `grep` + what you are looking for... 30 | Let say the port already used is `54905`, you would run: 31 | 32 | ``` 33 | $ netstat -vanp tcp | grep 54905 34 | tcp4 0 0 127.0.0.1.54905 *.* LISTEN 131072 131072 46725 0 35 | ``` 36 | 37 | ### Manually `kill` the process 38 | 39 | When running `netstat -vanp tcp`, the columns titles are shown. 40 | 41 | Spot the `pid` column in the output... In our example the `pid` value for the process using the port `54905` is `46725`... 42 | 43 | Just run `kill 46725` and make sure it worked by running `netstat -vanp tcp | grep 54905`. 44 | -------------------------------------------------------------------------------- /tips/live-reload-with-node+express.md: -------------------------------------------------------------------------------- 1 | # Using live-reload when starting a web app with Node and Express 2 | 3 | ## Notes 4 | 5 | This tip was written via an [issue by @Bondifrench on 24 Jun 2015](https://github.com/keithamus/npm-scripts-example/issues/25). 6 | 7 | See [Using connect-livereload in an Express node app](http://stackoverflow.com/questions/31022819/using-connect-livereload-in-an-express-node-app) on Stack Overflow. 8 | -------------------------------------------------------------------------------- /tips/run-commands-when-files-change.md: -------------------------------------------------------------------------------- 1 | # Run arbitrary commands when files change 2 | 3 | ## Notes 4 | 5 | This tip was written via an [issue by @jab on 24 Jan 2015](https://github.com/keithamus/npm-scripts-example/issues/10). 6 | 7 | ## Message 8 | 9 | Came across your post and thought you might find http://entrproject.org/ (which I also just came across) interesting: 10 | 11 | > entr(1) 12 | > Run arbitrary commands when files change 13 | > ... 14 | > Some graphical applications... ship with a --watch option which reloads the document whenever the source file is modified. This is useful, but it is even better for applications to provide a programmatic means of refreshing the display. The browser add-on LiveReload has attempted to solve this problem for web developers by injecting JavaScript that listens on a web socket. The solution does not need to be complex, indeed this is all that is required: 15 | > `$ ls *.css *.html | entr reload-browser Firefox` 16 | > reload-browser is a script bundled with the 3.0 release which uses xdotool or AppleScript to send a refresh keystroke to the active tab in your browser. 17 | 18 | related: #6 19 | 20 | ## PS 21 | 22 | I believe the entr tool is not a npm package so it is out of scope of this project... 23 | -------------------------------------------------------------------------------- /tips/use-javascript-in-package-file.md: -------------------------------------------------------------------------------- 1 | # A tool to use JS with npm scripts 2 | 3 | ## Notes 4 | 5 | This tip was written via an [issue by @corysimmons on 16 Oct 2016](https://github.com/keithamus/npm-scripts-example/issues/38). 6 | 7 | ## Message 8 | 9 | [package-script-manager](https://github.com/corysimmons/package-script-manager) 10 | 11 | Sorry if this is the wrong place (don't want to have to get a Twitter account and couldn't find your email anywhere) but wanted to ping you about this thing since "JSON is restrictive" is the biggest drawback of npm scripts. 12 | 13 | This seems to fix it. Let me know what you think and if you think of any cool ways to use it. 14 | --------------------------------------------------------------------------------