Skip to content

Commit

Permalink
feat: drop support for transpiling the code that is being prevaled (#59)
Browse files Browse the repository at this point in the history
It cause way too many weird bugs that take a TON of time to track down.

BREAKING CHANGE: Code that's being prevaled will no longer be transpiled. You should either transpile it ahead of time or only write the code in a version of JavaScript that runs natively in the version of node you're running.
  • Loading branch information
Kent C. Dodds authored Jun 27, 2018
1 parent d8be253 commit b0f94b9
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 155 deletions.
86 changes: 10 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ See more below.
- [Use with `babel-plugin-macros`](#use-with-babel-plugin-macros)
- [Examples](#examples)
- [Notes](#notes)
- [Limitations](#limitations)
- [Code transpilation](#code-transpilation)
- [FAQ](#faq)
- [How is this different from prepack?](#how-is-this-different-from-prepack)
- [How is this different from webpack loaders?](#how-is-this-different-from-webpack-loaders)
Expand All @@ -122,9 +120,8 @@ Important notes:

1. All code run by `preval` is _not_ run in a sandboxed environment
2. All code _must_ run synchronously.
3. The code string that preval evaluates will be transpiled, however, only that
code string will be prevaled. Learn more about this in the
[limitations](#limitations) section below.
3. 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).

> You may like to watch
> [this YouTube video](https://www.youtube.com/watch?v=1queadQ0048&list=PLV5CVI1eNcJgCrPH_e6d57KRUTiDZgs0u)
Expand Down Expand Up @@ -339,77 +336,13 @@ Ok:
}
```

## Limitations

### Code transpilation

It's recommended that code you want to preval be written in a way that works in
the version of Node that you're running. That said, some code will be
transpiled. If you for some strange reason _really_ want to write your preval
code in a way that requires it to be transpiled, then expand here:

<details>
<summary>Expand (beware)</summary>

Here are a few examples of what will and wont be transpiled by preval:

> This is assuming that you've configured babel to support ESModule syntax but
> you're using a node version which does not support ESModules natively.
```javascript
// a.js // this file can use ESModules. Regular babel handles that.
import value from /* preval */ './b'

// b.js // this file can use ESModules. preval handles that.
import c from './c'
export default c

// c.js // this file cannot have ESModules in it.
// Neither preval nor babel will transpile this file's contents
module.exports = 'c'
```

```javascript
// this file can use ESModules
var x = preval`
// this string can use ESModules
import b from 'b.js'
// however b.js and it's dependents cannot
`
```

```javascript
// this file can use ESModules
// and b.js will be transpiled and evaluated
// by preval so it can use ESModules too
// but if b.js has dependencies then it cannot.
var x = preval.require('./b.js')
```

It's also notable that you can use preval in preval:

```javascript
// this file can use ESModules
var x = preval`
// this string can use ESModules
import b from /* preval */ 'b.js'
// b can use ESModules (but not it's dependencies).
`
```

Again, this is admittedly pretty confusing, so it's strongly recommended that
any files you preval are written in a way that they work in node without needing
transpilation.

</details>

## FAQ

### How is this different from prepack?

[`prepack`][prepack] is intended to be run on your final bundle after you've run your
webpack/etc magic on it. It does a TON of stuff, but the idea is that your code
should work with or without prepack.
[`prepack`][prepack] is intended to be run on your final bundle after you've run
your webpack/etc magic on it. It does a TON of stuff, but the idea is that your
code should work with or without prepack.

`babel-plugin-preval` is intended to let you write code that would _not_ work
otherwise. Doing things like reading something from the file system are not
Expand All @@ -420,14 +353,15 @@ possible in the browser (or with prepack), but `preval` enables you to do this.
This plugin was inspired by webpack's [val-loader][val-loader]. The benefit of
using this over that loader (or any other loader) is that it integrates with
your existing babel pipeline. This is especially useful for the server where
you're probably not bundling your code with [`webpack`][webpack], but you may be using
babel. (If you're not using either, configuring babel for this would be easier
than configuring webpack for `val-loader`).
you're probably not bundling your code with [`webpack`][webpack], but you may be
using babel. (If you're not using either, configuring babel for this would be
easier than configuring webpack for `val-loader`).

In addition, you can implement pretty much any webpack loader using
`babel-plugin-preval`.

If you want to learn more, check `webpack` documentations about [`loaders`][webpack-loaders].
If you want to learn more, check `webpack` documentations about
[`loaders`][webpack-loaders].

## Inspiration

Expand Down
3 changes: 0 additions & 3 deletions src/__tests__/.babelrc

This file was deleted.

51 changes: 11 additions & 40 deletions src/__tests__/__snapshots__/index.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const x = preval\`
const x = {
"val": "# fixture\\n\\nThis is some file thing...\\n",
"getSplit": function getSplit(splitDelimiter) {
"getSplit": function (splitDelimiter) {
return x.val.split(splitDelimiter);
}
};
Expand All @@ -34,19 +34,6 @@ const x = "<PROJECT_ROOT>/src/__tests__/index.js";
`;
exports[`preval can use preval in preval: can use preval in preval 1`] = `
var x = preval\`
import message from /* preval */ './fixtures/es6'
export default message
\`
↓ ↓ ↓ ↓ ↓ ↓
var x = "this string used exported default";
`;
exports[`preval dynamic error: dynamic error 1`] = `
const x = preval\`module.exports = "\${dynamic}"\`
Expand All @@ -70,6 +57,16 @@ module.exports = undefined;
`;
exports[`preval handles transpiled modules (uses default export): handles transpiled modules (uses default export) 1`] = `
let one = preval.require('./fixtures/es6-identity.js', 1)
↓ ↓ ↓ ↓ ↓ ↓
let one = 1;
`;
exports[`preval import comment (with extras before): import comment (with extras before) 1`] = `
import x from /* this is extra stuff */ /* preval */ "./fixtures/compute-one.js"
Expand Down Expand Up @@ -242,32 +239,6 @@ preval\`module.exports = "foo"\`
`;
exports[`preval transpiled: transpiled 1`] = `
export default preval\`
import path from 'path'
export default path.join(__dirname, 'something/whatever.js').replace(__dirname, '')
\`
↓ ↓ ↓ ↓ ↓ ↓
export default "/something/whatever.js";
`;
exports[`preval transpiles string contents: transpiles string contents 1`] = `
var x = preval\`
import one from './fixtures/compute-one'
export default one
\`
↓ ↓ ↓ ↓ ↓ ↓
var x = 1;
`;
exports[`preval with flow after: with flow after 1`] = `
// @preval
Expand Down
12 changes: 9 additions & 3 deletions src/__tests__/fixtures/es6-identity.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
export default acceptsArg
/* eslint-disable */
// codegen can't accept non-transpiled esmodules
// but it can handle transpiled esmodules
// so we're simulating a pre-transpiled module here
Object.defineProperty(exports, '__esModule', {
value: true,
})

function acceptsArg(arg) {
return arg
exports.default = function(input) {
return input
}
1 change: 0 additions & 1 deletion src/__tests__/fixtures/es6.js

This file was deleted.

4 changes: 0 additions & 4 deletions src/__tests__/fixtures/transpiled.js

This file was deleted.

14 changes: 2 additions & 12 deletions src/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ pluginTester({
\`
`,
'a-bunch-of-checks': fixture('a-bunch-of-checks'),
transpiled: fixture('transpiled'),
'dynamic error': error(
`const x = preval\`module.exports = "\${dynamic}"\``,
),
Expand Down Expand Up @@ -93,17 +92,8 @@ pluginTester({
// @preval
/* comment */
`),
'transpiles string contents': `
var x = preval\`
import one from './fixtures/compute-one'
export default one
\`
`,
'can use preval in preval': `
var x = preval\`
import message from /* preval */ './fixtures/es6'
export default message
\`
'handles transpiled modules (uses default export)': `
let one = preval.require('./fixtures/es6-identity.js', 1)
`,
},
})
19 changes: 6 additions & 13 deletions src/helpers.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,18 @@
const p = require('path')
const requireFromString = require('require-from-string')
const requireFromStringOfCode = require('require-from-string')
const objectToAST = require('./object-to-ast')

module.exports = {
getReplacement,
transformAndRequire,
requireFromString,
}

function transformAndRequire({
function requireFromString({
string: stringToPreval,
fileOpts,
fileOpts: {filename},
args = [],
babel,
}) {
const {filename, plugins, presets} = fileOpts
const {code} = babel.transform(stringToPreval, {
filename,
plugins,
presets,
})
let mod = requireFromString(code, filename)
let mod = requireFromStringOfCode(String(stringToPreval), filename)
mod = mod && mod.__esModule ? mod.default : mod

if (typeof mod === 'function') {
Expand All @@ -39,6 +32,6 @@ function transformAndRequire({
}

function getReplacement({string, fileOpts, args, babel}) {
const mod = transformAndRequire({string, fileOpts, args, babel})
const mod = requireFromString({string, fileOpts, args, babel})
return objectToAST(mod, {babel, fileOptions: fileOpts})
}
5 changes: 2 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const p = require('path')
const fs = require('fs')
// const printAST = require('ast-pretty-print')
const {getReplacement, transformAndRequire} = require('./helpers')
const {getReplacement, requireFromString} = require('./helpers')

module.exports = prevalPlugin

Expand Down Expand Up @@ -88,10 +88,9 @@ function prevalPlugin(babel) {
let argValues
if (prevalComment !== 'preval') {
const arg = prevalComment.replace(/preval\((.*)\)/, '$1').trim()
const argValue = transformAndRequire({
const argValue = requireFromString({
string: `module.exports = ${arg}`,
fileOpts,
babel,
})
argValues = [argValue]
}
Expand Down

0 comments on commit b0f94b9

Please sign in to comment.