
Security News
Feross on the 10 Minutes or Less Podcast: Nobody Reads the Code
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.
This is an example repository that demonstrates how to to write and publish a JS library for Node and browsers. You might find it useful as a scaffold or an example to work from if you are writing such a library and have questions about testing, automation, code quality, or how to distribute cross-compatible builds.
I wrote this based on my my experience writing/maintaining a lot of small Javascript libraries for Mozilla, many of which are internal.
If you're a colleague (hi!) building something that doesn't need to be published to npm, requires more intensive functional testing, and/or you want to use Task Cluster for CI, you might consider taking a look at Standard8's example-addon-repo. It shares a lot of the same principles but is more specifically focused on add-on development, rather than cross-compatible JS libraries.
This repo shows you how publish a library to npm that is usable in:
npm install and require,npm install and require, via a build system (e.g. Webpack or Browserify), orHere are some examples for each use case:
// Install
npm install libtastic --save
// Usage
const Libtastic = require("libtastic");
new Libtastic();
<!-- First, download the minified file from the dist/ directory -->
<script src="libtastic.min.js"></script>
<script>
// Libtastic will be available as a global
new Libtastic();
</script>
When you are publishing a library for Node and the browser, you should always consider the specific needs of your consumers. What version(s) should you support? How do you maintain backwards compatibility? What build systems are they likely to use? However, there are some things which I find are true most of the time:
You know this.
In this project, the unit tests are in the test/unit/ directory. You run them with npm test.
Don't rely on your own memory of the differences between Node and the browser – running your tests in both environments makes sure they really do run in both environments.
In this project, npm test triggers a mocha test task AND a karma test task, which run in node and Firefox respectively. You should have a look at the test/karma.conf.js file for how test-running is set up for Firefox.
Sometimes this isn't possible, but if you can, install dependencies AND dev dependencies (like mocha, karma, etc.) via npm with --save/--save-dev and use the npm scripts section of package.json to run tasks like test running, linting, etc. This makes it easier to use and work on your library and prevents unexpected version mismatches.
In this project, all tasks are defined as scripts in package.json and can be run by invoking npm run [taskname].
There are a few reasons for this. One, it helps prevent human error, like forgetting to publish a tag. Two, if helps decouple the publishing process from your own environment/authentication, which is especially helpful if you're working with a team.
You know this, of course – the trade off is that automating deploys is often time-consuming and complicated. For most JS libraries however, if you are using Travis CI and publishing to npm, it is really quite simple, and you should do it now.
In this project, you can publish by running the npm version task, which triggers an automated process of pushing a tag to Github and Travis publishing that tag to npm. See the .travis.yml file and the "More about publishing" section below for more details.
There are a lot of (valid) opinions about how much test coverage matters, but regardless of what percentage you're targeting, test coverage reporting can actually reveal accidental bugs and help automatically remind new contributors to include tests with patches.
In this project, code is instrumented with instanbul, which generates local coverage reports in coverage/ every time the mocha tests are run. On Travis, these coverage reports are sent to Coveralls, and reported back to Github. You should look at the test:node task for how istanbul is set up, and this page for an example of what Coveralls looks like.
Linting helps new contributors, catches some bugs, and makes code easier to read.
This project uses eslint for linting. You should take a look at the .eslintignore and .eslintrc files and the test:lint task in package.json if you want to learn more.
Not everyone uses a build tool or module loader for browser JS, such as Webpack, Browserify, etc. In addition, having a pre-built version available also makes it easy for someone to quickly prototype or create a test case in an online code sharing tool. For this reason, I like to distribute a pre-built, production-optimized version of my library, that exports the library as a global.
This project uses Webpack to generate a pre-built version, which is configured in webpack.config.js and triggered by the npm run package command defined in package.json. The actual asset is called libtastic.min.js, and is added to the dist/ folder.
Not everyone agrees with this, but I'm personally not a fan of committing compiled dependencies – they make git histories harder to read and add a lot of noise. However, npm presents a solution for this – you can still include your built files in the published package even if they are in .gitignore, by explicitly excluding them in .npmignore with the ! operator.
In this project, the dist/ folder is gitignored (it gets generated if you run npm run package). I don't like to use the task name build, because npm run build can be easily confused with npm build, which already exists in the npm cli. Take a look at the .npmignore to see how it is excluded from ignoring, and don't forget to actually run your npm run package command before publishing in .travis.yml!
This project also includes an integration test, which can be found in test/integration/. It is configured in karma.integration.config.js and run with karma. What it does is load the pre-built file from the dist/ directory into the browser, and ensures that the global variable Libtastic exists. This test ensures:
npm run package before publishing (the test fails if npm run package wasn't run first)Overkill? Maybe. But it helps reassure me I didn't mess up by weback export config or publishing flow.
All source files related to the project should be placed in the src/ directory. Remember two things here:
main property in package.json to point to the entry point file of the library (in this case, src/libtastic.js)webpack.config.js to the entry point file as wellIf you want to publish a new version, just run npm version [patch/minor/major]. That's it.
Run npm version patch in your terminal for a new patch version, npm version minor for a minor version, etc. (see npm version) This will trigger the following:
preversion script defined in package.json)package.json will be updated with the new version number and a git tag will be created.origin master. Note that if you normally push code to somewhere other than origin master, or if you don't want to automatically push, you should update the postversion script.dist/ WILL be published to npm because they are re-included in .npmignore.The Travis configuration in .travis.yml sets up a few things for CI:
In order to get this to work, you must do three things.
travis enable -r yourgithub/yourrepodeploy section of .travis.yml for npm publishing. You can find instructions for finding your key and encrypting it here. I usually create and authenticate a new single-purpose npm account (such as libtastic-publisher) for this publishing, but you can also just use your personal account.FAQs
An example lib for node and the browser
We found that libtastic demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.

Research
/Security News
Campaign of 108 extensions harvests identities, steals sessions, and adds backdoors to browsers, all tied to the same C2 infrastructure.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.