-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
2,629 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
name: Node CI | ||
|
||
on: [push] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
|
||
strategy: | ||
matrix: | ||
node-version: [14.x, 16.x, 18.x, 19.x] | ||
|
||
steps: | ||
- uses: actions/checkout@v1 | ||
- name: Use Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v1 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
- name: Install packages | ||
run: yarn install | ||
- name: Run tests | ||
run: yarn test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules/ | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,122 @@ | ||
# parcel-transformer-preval | ||
# parcel-transformer-preval | ||
|
||
Pre-evaluate code at build-time | ||
|
||
## The problem | ||
|
||
You need to do some dynamic stuff, but don’t want to do it at runtime. Or maybe you want to do stuff like read the file system to get a list of files and you can’t do that in the browser. | ||
|
||
## Table of Contents | ||
|
||
- [parcel-transformer-preval](#parcel-transformer-preval) | ||
- [The problem](#the-problem) | ||
- [Table of Contents](#table-of-contents) | ||
- [Installation](#installation) | ||
- [Usage](#usage) | ||
- [Important notes:](#important-notes) | ||
- [Parcel config](#parcel-config) | ||
- [Simple example](#simple-example) | ||
- [Serialization](#serialization) | ||
- [How is this different from `babel-plugin-preval`?](#how-is-this-different-from-babel-plugin-preval) | ||
|
||
## Installation | ||
|
||
As this package will be used during the build process with [Parcel](https://parceljs.org/), it needs to live in your `devDependencies`: | ||
|
||
```bash | ||
npm install --save-dev parcel-transformer-preval | ||
# or | ||
yarn add -D parcel-transformer-preval | ||
``` | ||
|
||
## Usage | ||
|
||
### Important notes: | ||
|
||
1. This is a [Parcel](https://parceljs.org/) plugin. | ||
2. All code run by `preval` is _not_ run in a sandboxed environment. | ||
3. All code _must_ run synchronously. | ||
4. Code that is run by preval is not transpiled so it must run natively in the version of node you’re running. (cannot use ES Modules). | ||
5. All exported values need to be serializable as JSON for better interop between node environment and the runtime. | ||
|
||
### Parcel config | ||
|
||
In your `.parcelrc` file, you need enable the preval transformer on `*.preval.js` files (it needs to be the 1st one in the list): | ||
|
||
```json | ||
{ | ||
"extends": "@parcel/config-default", | ||
"transformers": { | ||
"*.preval.js": ["parcel-transformer-preval", "..."] | ||
} | ||
} | ||
``` | ||
|
||
And now, you’re ready to use it. | ||
|
||
### Simple example | ||
|
||
Every file imported that ends in `.preval.js` will be evaluated by `Parcel` at build time: | ||
|
||
```js | ||
// file.preval.js | ||
module.exports = 1 + 3; | ||
// other-file.js | ||
import result from "./file.preval.js"; | ||
|
||
// ↓ ↓ ↓ ↓ ↓ ↓ | ||
|
||
// other-file.js | ||
const result = 4; | ||
``` | ||
|
||
### Serialization | ||
|
||
As mentioned in the [important notes](#important-notes), `preval` uses JSON serialization. So it can only handle: | ||
|
||
- numbers | ||
- strings | ||
- arrays | ||
- simple objects | ||
|
||
But not: | ||
|
||
- sets | ||
- maps | ||
- functions | ||
- classes | ||
- in general complex “objects” | ||
|
||
```js | ||
// Not supported | ||
module.exports = new Set(); | ||
module.exports = new Map(); | ||
module.exports = new Date(); | ||
module.exports = class A {}; | ||
module.exports = () => {}; | ||
module.exports = function () {}; | ||
``` | ||
|
||
## How is this different from `babel-plugin-preval`? | ||
|
||
This plugin is heavily inspired by [`babel-plugin-preval`](https://github.com/kentcdodds/babel-plugin-preval). We could even say that this plugin is a port of the babel plugin for Parcel with a few differences: | ||
|
||
This plugin doesn’t support: | ||
|
||
- template tags: `` preval`module.exports = …`; `` | ||
- import comments: `import x from /* preval */ './something'` | ||
- `preval.require`s: `preval.require('./something')` | ||
- preval file comments: `// @preval` | ||
- exporting a function. | ||
|
||
The reason behind the 4 first differences is because when using it in bigger projects, we realized that being able to easily understand in which environment the code will run. | ||
|
||
So instead of having to tell mention from another file that the file we’re importing needs to be prevaled (the import comments and `preval.require`), we found that the file name was a better indicator to reviewers. | ||
As the transformer is now only based on the file name, there is no need for `@preval` comments. | ||
|
||
Only using the file name allows you to be able to easily configure: | ||
|
||
- ESLint | ||
- TypeScript | ||
- Parcel | ||
- and others |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"name": "parcel-transformer-preval", | ||
"version": "0.0.0", | ||
"description": "Pre-evaluate code at build-time", | ||
"main": "src/index.js", | ||
"repository": "[email protected]:Ayc0/parcel-transformer-preval.git", | ||
"author": "Ayc0 <[email protected]>", | ||
"license": "MIT", | ||
"dependencies": { | ||
"@parcel/plugin": "^2.8.0", | ||
"require-from-string": "^2.0.2" | ||
}, | ||
"files": [ | ||
"src" | ||
], | ||
"devDependencies": { | ||
"@parcel/config-default": "^2.8.0", | ||
"@parcel/core": "^2.8.0", | ||
"@parcel/fs": "^2.8.0", | ||
"ava": "^5.0.1", | ||
"parcel-transformer-preval": "link:." | ||
}, | ||
"scripts": { | ||
"test": "ava" | ||
}, | ||
"ava": { | ||
"files": [ | ||
"!tests/stubs" | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
const { Transformer } = require("@parcel/plugin"); | ||
const requireFromString = require("require-from-string"); | ||
|
||
const prevalTransfomer = new Transformer({ | ||
async transform({ asset }) { | ||
const requireCacheKeysBeforeRun = Object.keys(require.cache); | ||
const output = requireFromString(await asset.getCode()); // execute file | ||
const requireCacheKeysAfterRun = Object.keys(require.cache); | ||
|
||
// Delete elements that were added to the cache by the script | ||
// This is to ease re-runs in dev mode if the other dependencies have changed | ||
// without having to stop parcel and restart it. | ||
for (const cacheKey of requireCacheKeysAfterRun) { | ||
if (requireCacheKeysBeforeRun.includes(cacheKey)) { | ||
continue; | ||
} | ||
delete require.cache[cacheKey]; | ||
} | ||
|
||
asset.setCode(`module.exports = ${JSON.stringify(output)}`); | ||
asset.setMap(null); // impossible to relate the new code and the old one | ||
|
||
return [asset]; | ||
}, | ||
}); | ||
|
||
module.exports = prevalTransfomer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
const { Parcel, createWorkerFarm } = require("@parcel/core"); | ||
const { MemoryFS } = require("@parcel/fs"); | ||
const vm = require("node:vm"); | ||
|
||
const test = require("ava"); | ||
|
||
const build = async (input) => { | ||
const workerFarm = createWorkerFarm(); | ||
const outputFS = new MemoryFS(workerFarm); | ||
|
||
let bundler = new Parcel({ | ||
entries: input, | ||
config: require.resolve("./stubs/config.json"), | ||
workerFarm, | ||
outputFS, | ||
}); | ||
|
||
try { | ||
let { bundleGraph } = await bundler.run(); | ||
|
||
for (let bundle of bundleGraph.getBundles()) { | ||
const code = await outputFS.readFile(bundle.filePath, "utf8"); | ||
const context = { module: {} }; | ||
vm.runInNewContext(code, context); | ||
return { code, value: context.module.exports }; | ||
} | ||
} finally { | ||
await workerFarm.end(); | ||
} | ||
}; | ||
|
||
test.serial("bundles number properly", async (t) => { | ||
const { code, value } = await build( | ||
require.resolve("./stubs/number.preval.js") | ||
); | ||
t.is(true, code.includes("module.exports = 13")); | ||
t.is(13, value); | ||
t.pass(); | ||
}); | ||
|
||
test.serial( | ||
"bundles array properly & can work with native modules", | ||
async (t) => { | ||
const { code, value } = await build( | ||
require.resolve("./stubs/fs-array.preval.js") | ||
); | ||
t.is(false, code.includes("require")); | ||
t.is(false, code.includes("readdirSync")); | ||
|
||
t.deepEqual(value, [ | ||
"config.json", | ||
"fs-array.preval.js", | ||
"number.preval.js", | ||
"wrapper.js", | ||
]); | ||
t.pass(); | ||
} | ||
); | ||
|
||
test.serial("bundles when sub files are preval files", async (t) => { | ||
const { value } = await build(require.resolve("./stubs/wrapper.js")); | ||
|
||
t.deepEqual(value, { | ||
number: 13, | ||
fsArray: [ | ||
"config.json", | ||
"fs-array.preval.js", | ||
"number.preval.js", | ||
"wrapper.js", | ||
], | ||
}); | ||
t.pass(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"extends": "@parcel/config-default", | ||
"transformers": { | ||
"*.preval.js": ["parcel-transformer-preval", "..."] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require("fs").readdirSync("./tests/stubs"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = 1 + 12; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import number from "./number.preval"; | ||
import fsArray from "./fs-array.preval"; | ||
|
||
module.exports = { | ||
number, | ||
fsArray, | ||
}; |
Oops, something went wrong.