Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add browser compatible builds #110

Merged
merged 10 commits into from
Dec 23, 2021
Merged

Conversation

aron
Copy link
Contributor

@aron aron commented Dec 19, 2021

Okay, so this PR adds a few new pieces that enable browser compatible builds as well as clearer entrypoints for the node modules too. The following table illustrates the compatibility matrix now provided.

node browser
commonjs ./src/index.cjs N/A
esm ./src/index.mjs ./dist/opa-wasm-browser.esm.js
global N/A ./dist/opa-wasm-browser.js

These entrypoints are exposed in the package.json file using the exports property supported by Node 12 and newer. Older Node versions will fallback to the main field and require the commonjs package.

  1. The index.cjs will be used by any Node versions using require() to import the module.
  2. The index.mjs will be used by any Node versions using import opa from "..." to import the module.
  3. The opa-wasm-browser.esm.js can be used by all modern browsers and contains all bundled dependencies.
  4. The opa-wasm-browser.js file will export an opa global (this could be updated to use a commonjs/umd shim by adding --banner and --footer properties as part of the build).

I've added some examples to the bottom of the README to show how these would be used.

Node Modules

Not much has changed in the core code, I've added the two entrypoints index.cjs and index.mjs to support the two module types as described in the Node docs. I've also fixed the TextEncoding/Decoding that was discussed previously.

Browser Modules

This change adds a new dist directory containing the two files described above. These are now generated by the ./build.sh script and use esbuild. I've found that pretty easy to use and very fast. I looked into microbundle as well but that project is not aimed at commonjs packages nor for bundling dependencies. Webpack and Rollup required too much configuration for me.

Once published both of these generated modules should then be consumable from a CDN like unpkg for use directly in a webpage or projects can install and consume the package directly.

Testing

I've tested this locally using npm link to run it on a few test projects. Creating a node esm project and commonjs project both work fine. As does the commonjs project on Node 10.

I've created a basic integration script that uses pupetteer to verify that the browser packages also work as expected. This doesn't do a whole lot just imports the global script and then the esm script and verifies that the policy can be loaded and evaluated.

TypeScript

I moved the TypeScript files into the dist directory too to keep things simple and I've moved the generation into the ./build.sh script. We still generate files for the all the modules though it looks like only opa.d.ts is used, I've tested this locally with a TypeScript project and my editor picks up the types as expected. I've updated the types field in the package.json.

Package & Publishing

I've rejigged a bunch of the package.json, we now have the new exports field mentioned above and the updated typesfield. The last part was to add the files property to define a safelist of files to be included in the bundle. The current output from npm pack is below, I'd appreciate it if you could let me know if anything is missing.

Output from npm pack --json:
[
  {
    "id": "@open-policy-agent/opa-wasm@1.5.0",
    "name": "@open-policy-agent/opa-wasm",
    "version": "1.5.0",
    "size": 215502,
    "unpackedSize": 874429,
    "shasum": "a7da98b9d7810bc5247dfe507847dea84ff202e1",
    "integrity": "sha512-wWP8cVtIUELIOx9C4ZExCIOWMt2y4J7c4xWhGK2sZmmeNXxnsiXLhxalhzdfDK3lsI2mdTt1LaTTyu3etwprPA==",
    "filename": "open-policy-agent-opa-wasm-1.5.0.tgz",
    "files": [
      {
        "path": "LICENSE",
        "size": 11357,
        "mode": 420
      },
      {
        "path": "src/index.cjs",
        "size": 35,
        "mode": 420
      },
      {
        "path": "src/builtins/index.js",
        "size": 207,
        "mode": 420
      },
      {
        "path": "src/builtins/json.js",
        "size": 281,
        "mode": 420
      },
      {
        "path": "dist/opa-wasm-browser.esm.js",
        "size": 93379,
        "mode": 420
      },
      {
        "path": "dist/opa-wasm-browser.js",
        "size": 93386,
        "mode": 420
      },
      {
        "path": "src/opa.js",
        "size": 12874,
        "mode": 420
      },
      {
        "path": "src/builtins/regex.js",
        "size": 110,
        "mode": 420
      },
      {
        "path": "src/builtins/strings.js",
        "size": 133,
        "mode": 420
      },
      {
        "path": "src/builtins/yaml.js",
        "size": 1077,
        "mode": 420
      },
      {
        "path": "capabilities.json",
        "size": 39011,
        "mode": 420
      },
      {
        "path": "package.json",
        "size": 1491,
        "mode": 420
      },
      {
        "path": "dist/opa-wasm-browser.esm.js.map",
        "size": 305932,
        "mode": 420
      },
      {
        "path": "dist/opa-wasm-browser.js.map",
        "size": 305932,
        "mode": 420
      },
      {
        "path": "README.md",
        "size": 5837,
        "mode": 420
      },
      {
        "path": "src/index.mjs",
        "size": 124,
        "mode": 420
      },
      {
        "path": "dist/types/opa.d.ts",
        "size": 3263,
        "mode": 420
      }
    ],
    "entryCount": 17,
    "bundled": []
  }
]


This change also opens up the door for #38 if you are still looking to convert the codebase over to the new module system. Though I would potentially wait until moving away from node 10 to do this otherwise you're going to need to produce a commonjs compatible build just for that version.

Let me know what you think so far, apologies for making it into a bigger change than potentially needed, feel free to take whichever bits are useful. I've got a little more time next week to look into this.

As for next steps, I think if this merges it would be a good idea to try and publish an alpha/beta version first just to ensure that everything is still working in the wild.

@aron aron force-pushed the feat/browser branch 4 times, most recently from a1ae927 to 6ff37b9 Compare December 20, 2021 00:10
@srenatus
Copy link
Contributor

Thanks a lot for looking into this! I like what see here a lot 👏

For clarification: We're building a "special" browser-focused ES module here, so we're don't put it into the module field of package.json, correct? (When and where would you consume a "non-browser" ESM? 💭 Typescript?)

@jorgecasar: If you find the time, would you mind reviewing this, too? For one thing, you have been following the browser use case; and looked into #38 as well.

@aron aron force-pushed the feat/browser branch 2 times, most recently from 333d2e0 to 988f4b9 Compare December 21, 2021 23:27
Signed-off-by: Aron Carroll <self@aroncarroll.com>
Signed-off-by: Aron Carroll <self@aroncarroll.com>
Signed-off-by: Aron Carroll <self@aroncarroll.com>
Signed-off-by: Aron Carroll <self@aroncarroll.com>
@aron aron changed the title feat: ESM compatible browser build feat: add browser compatible builds Dec 21, 2021
@aron aron changed the title feat: add browser compatible builds Add browser compatible builds Dec 21, 2021
Signed-off-by: Aron Carroll <self@aroncarroll.com>
@aron aron force-pushed the feat/browser branch 2 times, most recently from 77eb8f3 to 8ec1936 Compare December 22, 2021 00:13
aron and others added 4 commits December 22, 2021 00:18
Signed-off-by: Aron Carroll <self@aroncarroll.com>
Signed-off-by: Aron Carroll <self@aroncarroll.com>
Signed-off-by: Aron Carroll <self@aroncarroll.com>
Signed-off-by: Aron Carroll <self@aroncarroll.com>
@aron
Copy link
Contributor Author

aron commented Dec 22, 2021

For clarification: We're building a "special" browser-focused ES module here, so we're don't put it into the module field of package.json, correct? (When and where would you consume a "non-browser" ESM? 💭 Typescript?)

I've updated the description, hopefully this clarifies things a little. I ended up doing a bunch more reading on the different fields in the package.json file. It turns out the module field isn't used by Node and the browser one takes precedence so I've dropped it.

Node in general supports both esm and commonjs modules and will prefer the one used by the importing project. We now just use a shim called index.mjs to provide an ESM export. This is mostly there to allow both import { loadPolicy " from and `import opa from" syntaxes in the Node ecosystem (The browser ecosystem only supports the latter).

TypeScript I think will still use the CommonJS version.

@aron aron marked this pull request as ready for review December 22, 2021 00:27
@jorgecasar
Copy link
Contributor

Great work @aron.

For browser, I consider a good practice expose packages in ESM and delegate to the user to transpile to ES5 if needed.

It could be great if we set the source code to ESM and build the commonJs version for older version of nodeJS. But it could be done in a close future.

Copy link
Contributor

@srenatus srenatus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much! 💯

@srenatus srenatus merged commit 09a62db into open-policy-agent:main Dec 23, 2021
@aron aron deleted the feat/browser branch December 23, 2021 16:03
srenatus added a commit to srenatus/npm-opa-wasm that referenced this pull request Jan 10, 2022
Using deno was enabled by
open-policy-agent#110.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
srenatus added a commit to srenatus/npm-opa-wasm that referenced this pull request Jan 10, 2022
Using deno was enabled by
open-policy-agent#110.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
srenatus added a commit to srenatus/npm-opa-wasm that referenced this pull request Jan 10, 2022
Using deno was enabled by
open-policy-agent#110.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
srenatus added a commit that referenced this pull request Jan 10, 2022
Using deno was enabled by
#110.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants