Using npm in your Cordova Workflow


I decided to try npm (nodejs) and see how it could streamline my workflow. If you’ve been using Cordova or PhoneGap, you probably already have npm installed – you used npm to install either one in the first place. But it can do so much more.

Test Drive npm

1. I created an empty test folder called npmTest. Open the Terminal console and set it to start with your test project’s folder (type “cd” and a space, then drag the project’s folder to the console window, click on Terminal, then hit Enter). Type the following command in Terminal to get a list of all the packages you have downloaded for your project:

npm ls

Very likely it returns, “empty.”

2. I know there’s a program which validates JavaScript called jshint. I need to do a search on npm to find out the exact npm package name. Stretch the Terminal window as wide as you can and type:

npm search jshint

This described all packages containing “jshint” in the package name or description. If the package begins with grunt- or gulp- or othername-, then it is a version designed to be used with grunt or other named packages. I’m not using grunt or another package manager, just npm, so I avoided packages with those prefixes. This search gave me “jshint” as the package I wanted, among other titles.

You can visit the following link, type in the package name in the search, and click through to learn more about it to see if it’s right for your application: http://www.npmjs.com/

3. Now it’s time to install the package with:

npm install jshint

It’s installed locally: a /node_modules folder is created in the root of your project and the files downloaded there. Open it to see what packages have been downloaded. It’ll have a subfolder with the same name as the npm name; in our case, /jshint. (“npm ls” typed into the Terminal will also list your files, but it takes much longer.) Sometimes I had to do the run command twice to get the files to install; just check the folder to make sure it appears.

4. I went ahead and searched for and installed image optimizers for png and jpg (optimg for png and jpgo for jpg), and a css minifier, ycssmin:

npm install optimg
npm install jpgo
npm install ycssmin

5. How do I run the npm files on my project? npm looks for package.json in the project’s root folder to know what scripts to run. In my example, note the placement of all the commas, use of straight quotes and not curly quotes; and in my text editor the text file is encoded as UTF-8 (without BOM):

package.json:

{
 "name": "npmTest",
 "devDependencies": {
 "jshint": "latest",
 "optimg": "latest",
 "jpgo": "latest",
 "ycssmin": "latest"
 },
 "scripts": {
 "lint": "jshint **.js",
 "png": "optimg",
 "jpg": "jpgo",
 "css": "ycssmin **.css"
 }
}

Explanation of script:
To the right of “name” is the name of your Cordova project.
Under “devDependencies,” put the name of the package and either “latest” or the version number you want to use, if known. It is better to use the version number instead of “latest” so the script won’t break in later versions. I will revise this when I learn more. But it works as is.
Under “scripts,” the first word is a command text you make up to run the package (“lint” will run jshint); the right section has the program to execute and any arguments — in the case of jshint, a particular file type to apply the command to: .js. The ** includes all such files.

This site gives the correct syntax when forming the package.json file: http://json.org/

6. Check the script’s correctness by pasting it into the validator field at
http://jsonlint.com/. I have a brief Error Messages section at the bottom of this article that might address some of your errors.

7. To test the above scripts, add one or more .js files and a couple of jpgs. Add a CSS file. I grabbed these from another Cordova project. Use the commands you wrote in package.json under “scripts,” one after another, as needed, when the previous command is finished:

npm run lint
npm run png
npm run jpg

They will open the corresponding file in /node_modules of the same name and execute the scripts written there. The lint command gave me a list of errors in Terminal (without changing or correcting the original file). The png and jpg commands gave me the input and output sizes of the files with the difference in percentages. The files were overwritten with the smaller versions. (So you’ll want to keep the full size files outside of your project.)

8. Test the CSS script:

npm run ycssmin

This will run the command, but show the compressed css in the Terminal and not overwrite the .css file. You could copy over the text from the Terminal window and name that file filename.css and rename the old version filename.old.css file in order to retain both.

The above instructions tell how to install your node modules locally, that is, per app. We could install them globally as well, that is, so the commands would work with any app at any location on your hard drive.

This command will list what npm packages you have globally, as well as the location where they are stored:

npm list -g

My global folder location is at /usr/local/lib, and the nested tree  list shows installation of bower, cordova, grunt-cli, grunt-init, ionic, ios-sim, phonegap, ripple emulator, weinre. (These are the names hanging right off the far left vertical line.)

To install a module globally, we would append -g to the install command:

npm install -g ycssmin

In this case, you don’t need to start the Terminal install commands from your project root folder. You do need to start from project root when you do “npm run” commands, though.

Error Messages

I’ve tried one package after another and got numerous errors I had difficulty resolving. Some packages just won’t install and I don’t know why not. Some packages could install, but the npm run command didn’t work. I suspect that I needed to add or remove arguments from the package.json file – or perhaps even from the npm run command – but the argument changes I tried in package.json did nothing. The usage guide online mentioned in step 2 was not helpful to me; it didn’t mention whether the package.json file syntax should change from what I had it above. I tried five or six “html” packages and all of them failed to work. What you see in this article worked for me.

1. Adding the -d flag may give more information on the error:

npm run -d html

2. Updating npm will resolve some errors that a later version addressed:

npm -g install npm@latest

3. Clearing the user cache may resolve some other problems:

npm cache clear

4. Double-check your bash file to make sure the PATH to npm is there:

export PATH=${PATH}:~/usr/local/bin
export PATH=${PATH}:~/usr/local/lib

5. It’s frustrating when you’re sure the syntax is correct but get errors in the Terminal and validators. When that happened, I made sure each quote was a straight quote and formatted the file as UTF-8 without BOM (see http://stackoverflow.com/questions/2223882/whats-different-between-utf-8-and-utf-8-without-bom). You can’t change this in TextEdit on the Mac. But in Sublime Text: File > Save with Encoding > UTF-8. And in TextWrangler: TextWrangler > Preferences > Text Encodings > Unicode (UTF-8). Then it validated fine. I noticed that nearly every time I edited the package.json file, nearby straight quotes changed into smart quotes. This site will convert from smart to straight quotes: http://dan.hersam.com/tools/smart-quotes.html

6. Not all npm packages will work with Cordova projects; they weren’t meant to. Visit the following link, type in the package name in the search, and click through to learn more about it to see if it’s right for your application: http://www.npmjs.com/ You may find that you need to download other files (dependencies) to make it work, or it wasn’t meant for the task you had in mind in the first place.

7. If you get npm ERR! messages in the Terminal, npm may tell you to contact the owner and include a message to pass on. For instance, with npm run imageoptim (an earlier try at an image optimizer package), I got:

npm ERR! Tell the author that this fails on your system:
npm ERR! npm run env-clear && npm run env-setup
npm ERR! You can get their info via:
npm ERR! npm owner ls imageoptim

So I got the email of the responsible person by typing npm owner ls imageoption, as instructed. npm already gave me the message to pass on the owner: “npm ERR! npm run env-clear && npm run env-setup.” At this point, you might as well search for another package. Enter /node_modules and delete the offending package’s files to remove clutter.

8. When using run command:
Error: 

npm ERR! Unexpected token "

Solution:
Change smart quotes to straight quotes. This site will convert: http://dan.hersam.com/tools/smart-quotes.html

9. When using run command:
Error:

npm ERR! Error: ENOENT, open '/Users/Steve/Documents/APPS/Test_Apps/package.json'

Solution:
ENOENT means “Error NO ENTry” or “No such directory entry.”
Open /node_modules to see if the files were actually installed. In my case, they were not. Run the install command again.

10. In the root of the project, npm writes its log messages in npm-debug.log. See if there are any extra clues there to help.

11. When using run command:
Error:

sh: html5-lint: command not found
npm ERR! Exit status 127

Solution:
“Exit status 127” indicates “command not found” and may indicate problems with the PATH or a typo.
This means that the program did not include a command for this script to work. The program is not compatible with this package.json method of scripting. Try another.

Useful Sites

http://tech.pro/tutorial/1190/package-managers-an-introductory-guide-for-the-uninitiated-front-end-developer

http://tobyho.com/2012/02/09/tour-of-npm/

http://browsenpm.org/help

https://www.npmjs.com/

https://docs.npmjs.com/

http://dontkry.com/posts/code/using-npm-on-the-client-side.html

http://blog.izs.me/post/1675072029/10-cool-things-you-probably-didnt-realize-npm

One thought on “Using npm in your Cordova Workflow

  1. Pingback: Workflow | iPhone Dev Log

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.