npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

parcel-optimizer-csp

v1.0.0

Published

Parcel 2.0+ plugin for generating Content Security Policy that also generates hashes for inline scripts.

Readme

parcel-optimizer-csp

A Parcel 2.0+ plugin for generating and inserting a CSP based on a super simple JSON config.

It automatically calculates a hash for your inline scripts and appends that to the script-src in the CSP so that browsers will run it.

Why I made this:

We have an inline script for Xchart.com that registers global error handlers. We do this as inline script, because if there's an error with loading a JS file required to run the app we want to know about it.

Another common reason would be inline scripts inserted for analytics.

BUT we're using a Content Security Policy (CSP) to prevent malicious scripts from being injected in any way.

CSP's script-src is one of the main reasons to use a CSP. It specifies valid sources for JavaScript and so, can completely prevent XSS (Cross-site scripting).

But, one of the tricky things people quickly notice is that if you have an inline snippet in the HTML that you pass to Parcel, like this:

<script>
  console.log('I might be an analytics snippet or something')
</script>

This code will not run when you've specified a script-src unless you've listed: 'unsafe-inline' which... kind of negates the whole point of setting a script-src to begin with.

If you're using CSP to prevent injected scripts, you can either specify a nonce or a hash of all the allowed scripts. A nonce is supposed to be unique from the server for each render, that doesn't work so well if you are building a PWA or static site (JAM Stack) when you may not have a server rendering on each request.

The other option is to calculate and specify a hash of each inline script that is allows to run: That's the main reason this plugin exists.

Why is it an Optimizer plugin?

It's very important that this happens last because if there's anything else that modifies the contents between the opening and closing <script> the hash would be different. So using the "optimize" stage made sense.

How to use it

Create a .csprc config at the root of your directory. It should contain something like this:

script-src is the only one that gets processed at all. Any other keys you specify are simply used to generate the final CSP string.

{
  "script-src": ["'self'", "polyfill.io"],
  "object-src": "'none'",
  "base-uri": "'none'"
}

Then, you must tell parcel to use the plugin. So you create / edit your .parcelrc as follows:

{
  "extends": "@parcel/config-default",
  "optimizers": {
    "*.html": ["...", "parcel-optimizer-csp"]
  }
}

Note: the "..." is important it tells parcel to do all the other stuff it would normally to do optimize. This just tacks on our new plugin at the end.

If with that .csprc and .parcelrc when you use Parcel to build your project for production this plugin will inject prepend the following CSP into the <head> your final HTML:

<meta
  http-equiv="Content-Security-Policy"
  content="script-src 'self' polyfill.io 'sha256-uhzHJtYe3+WE2TVTxNYzdpz1n2axTAdgGXDltcHRQvc='; object-src 'none'; base-uri 'none';"
/>

Please note: certain CSP values need to be in single quotes. For example: 'self' and 'none'. This plugin does not attempt to quote them for you. It simply inserts them the way you've specified them.

Running tests

npm test

install

npm install parcel-optimizer-csp

Change log

  • 1.0.0: First public release.

credits

If you like this follow @HenrikJoreteg on twitter.

license

MIT