Skip to content

Commit

Permalink
Add babel plugin for module tagging
Browse files Browse the repository at this point in the history
Adds babel-plugin-react-server to the react-server-cli webpack loader and
babel-preset-react-server.  Factor out react-server-module-tagger from
react-server-gulp-module-tagger to share module tagging format between
gulp and babel, and add tests to ensure prevent regressions.
  • Loading branch information
doug-wade committed Jun 10, 2016
1 parent 211ad97 commit a1fac00
Show file tree
Hide file tree
Showing 49 changed files with 590 additions and 152 deletions.
2 changes: 1 addition & 1 deletion docs/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,5 @@ var fooLogger = logging.getLogger(__LOGGER__({ label: "foo" }));
var barLogger = logging.getLogger(__LOGGER__({ label: "bar" }));
```

See [react-server-gulp-module-tagger]() for more details on how `__LOGGER__` is
See [module-tagging](/module-tagging) for more details on how `__LOGGER__` is
replaced.
26 changes: 26 additions & 0 deletions docs/module-tagging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Module tagging

To enable our [logging](/logging), we have to do a source transform to provide
the file name, and an isomorphic color object, to all of our logging instances.
This keeps coloring consistent for logging across the server and the client,
and makes for a much better developer experience by identifying the file from
which log lines and monitoring originated from on the server and the client
before transpilation and code splitting.

The easiest way to get started with module tagging is with
[react-server-cli](http://npmjs.com/packages/react-server-cli). If you're
already babelifying your code, you can use
[babel-plugin-react-server](http://npmjs.com/packages/babel-plugin-react-server)
, which is included in
[babel-preset-react-server](http://npmjs.com/packages/babel-preset-react-server)
to tag your react server modules. If you're already using gulp to build your
react server modules, you can use
[react-server-gulp-module-tagger](http://npmjs.com/packages/react-server-gulp-module-tagger)
. If you write custom build scripts, you can use the method that all of the
module taggers use to generate the module tags as well with
[react-server-module-tagger](http://npmjs.com/packages/react-server-module-tagger)
. Because internally all of the module taggers call the same module, it doesn't
matter which method you choose to tag your react server modules; the result is
exactly the same. We provide many methods for tagging your modules to make
react server easy to use (though it also makes testing and development quicker
and easier).
3 changes: 3 additions & 0 deletions packages/babel-plugin-react-server/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["es2015", "stage-0"]
}
3 changes: 3 additions & 0 deletions packages/babel-plugin-react-server/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
*.log
lib
3 changes: 3 additions & 0 deletions packages/babel-plugin-react-server/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
*.log
src
90 changes: 90 additions & 0 deletions packages/babel-plugin-react-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# babel-plugin-react-server

React Server transpilation

## Example

**In**

```js
var logger = require('react-server').logging.getLogger(__LOGGER__);
```

**Out**

```js
"use strict";

var logger = require('react-server').logging.getLogger({ name: 'module.name', color: {} });
```

## Installation

```sh
$ npm install babel-plugin-react-server
```

## Usage

### Via `.babelrc` (Recommended)

**.babelrc**

```json
{
"plugins": ["react-server"]
}
```

### Via CLI

```sh
$ babel --plugins react-server script.js
```

### Via Node API

```javascript
require("babel-core").transform("code", {
plugins: ["react-server"]
});
```


## Configuration

A fully configured babel plugin in your babelrc would look be

```json
{
"plugins": [
["react-server", {
"trim": "my-project.components.",
"token": "__LOGGER__"
}]
]
}
```


### Trim

A substring to trim off the front of the module name

```javascript
{
trim: "my-project.pages."
}
```

### Token

The token to replace in the source code with the module tag. By default, uses
the default logger token `__LOGGER__`, and two future reserved tokens,
`__CHANNEL__` and

```javascript
{
token: "__LOGGER__"
}
```
31 changes: 31 additions & 0 deletions packages/babel-plugin-react-server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "babel-plugin-react-server",
"version": "0.0.1",
"description": "Babel plugin for React Server transpilation",
"repository": "redfin/babel-plugin-react-server",
"author": "Doug Wade <[email protected]>",
"main": "lib/index.js",
"dependencies": {
"react-server-module-tagger": "^0.0.1"
},
"devDependencies": {
"babel-core": "^6.3.17",
"babel-preset-es2015": "^6.3.13",
"babel-preset-stage-0": "^6.3.13",
"mocha": "^2.2.5"
},
"scripts": {
"clean": "rm -rf lib npm-debug.log*",
"build": "babel src -d lib",
"test": "mocha --compilers js:babel-register",
"test:watch": "npm run test -- --watch",
"prepublish": "npm run clean && npm run build"
},
"keywords": [
"react",
"server",
"babel",
"plugin",
"babel-plugin"
]
}
34 changes: 34 additions & 0 deletions packages/babel-plugin-react-server/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import loggerSpec from 'react-server-module-tagger';
import path from 'path';

export default function({types: t }) {
return {
visitor: {
Identifier(p, state) {
const {node} = p;
const {name, type} = node;

const config = { trim: state.opts.trim };
const parent = path.resolve(path.join(process.cwd(), '..')) + path.sep;
const fp = this.file.opts.filename.replace(parent, '');
const file = { path: fp };
//TODO: Support labels
const moduleTag = loggerSpec.bind({ file, config })(fp);

let tokens;
if (state.opts.tokens) {
tokens = new Set(state.opts.tokens);
} else {
tokens = new Set(["__LOGGER__", "__CHANNEL__", "__CACHE__"]);
}

if (tokens.has(name)) {
// this strikes me as a dirty, nasty hack. I think it would be better
// to parse the object as json and coerce it to an array of
// ObjectProperties to construct an ObjectExpression
p.node.name = moduleTag;
}
}
}
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"plugins": [
["../../../src", { "tokens": ["BAR"] }]
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var logger = require('react-server').logging.getLogger(BAR);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var logger = require('react-server').logging.getLogger({"name":"babel-plugin-react-server.test.fixtures.configurable-token.actual","color":{"server":157,"client":"rgb(127,212,127)"}});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"plugins": [
["../../../src"]
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var logger = require('react-server').logging.getLogger(__LOGGER__);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var logger = require('react-server').logging.getLogger({"name":"babel-plugin-react-server.test.fixtures.example.actual","color":{"server":83,"client":"rgb(42,212,42)"}});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"plugins": [
["../../../src"]
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__CHANNEL__
__CACHE__
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{"name":"babel-plugin-react-server.test.fixtures.reserved-future-tokens.actual","color":{"server":203,"client":"rgb(212,42,42)"}};
{"name":"babel-plugin-react-server.test.fixtures.reserved-future-tokens.actual","color":{"server":203,"client":"rgb(212,42,42)"}};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"plugins": [
["../../../src", { "trim": "babel-plugin-react-server.test.fixtures." }]
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var logger = require('react-server').logging.getLogger(__LOGGER__);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var logger = require('react-server').logging.getLogger({"name":"trim.actual","color":{"server":73,"client":"rgb(42,127,127)"}});
26 changes: 26 additions & 0 deletions packages/babel-plugin-react-server/test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import path from 'path';
import fs from 'fs';
import assert from 'assert';
import { transformFileSync } from 'babel-core';
import plugin from '../src';

function trim(str) {
return str.replace(/^\s+|\s+$/, '');
}

describe('React Server transpilation', () => {
const fixturesDir = path.join(__dirname, 'fixtures');
fs.readdirSync(fixturesDir).map((caseName) => {
it(`should ${caseName.split('-').join(' ')}`, () => {
const fixtureDir = path.join(fixturesDir, caseName);
const actualPath = path.join(fixtureDir, 'actual.js');
const actual = transformFileSync(actualPath).code;

const expected = fs.readFileSync(
path.join(fixtureDir, 'expected.js')
).toString();

assert.equal(trim(actual), trim(expected));
});
});
});
16 changes: 4 additions & 12 deletions packages/babel-preset-react-server/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
module.exports = {
plugins: [
require('babel-plugin-transform-es2015-arrow-functions'),
require('babel-plugin-transform-es2015-block-scoping'),
require('babel-plugin-transform-es2015-classes'),
require('babel-plugin-transform-es2015-computed-properties'),
require('babel-plugin-transform-es2015-constants'),
require('babel-plugin-transform-es2015-destructuring'),
require('babel-plugin-transform-es2015-modules-commonjs'),
require('babel-plugin-transform-es2015-parameters'),
require('babel-plugin-transform-es2015-shorthand-properties'),
require('babel-plugin-transform-es2015-spread'),
require('babel-plugin-transform-es2015-template-literals'),
require('babel-plugin-transform-object-rest-spread'),
require('babel-plugin-react-server').default,
require('babel-plugin-transform-runtime'),
],
presets: [
require('babel-preset-es2015'),
require('babel-preset-react'),
require('babel-preset-stage-0'),
],
}
18 changes: 5 additions & 13 deletions packages/babel-preset-react-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,11 @@
"author": "Doug Wade <[email protected]>",
"license": "Apache License 2.0",
"dependencies": {
"babel-plugin-transform-es2015-arrow-functions": "^6.3.13",
"babel-plugin-transform-es2015-block-scoping": "^6.3.13",
"babel-plugin-transform-es2015-classes": "^6.3.13",
"babel-plugin-transform-es2015-computed-properties": "^6.3.13",
"babel-plugin-transform-es2015-constants": "^6.1.4",
"babel-plugin-transform-es2015-destructuring": "^6.3.13",
"babel-plugin-transform-es2015-modules-commonjs": "^6.3.13",
"babel-plugin-transform-es2015-parameters": "^6.3.13",
"babel-plugin-transform-es2015-shorthand-properties": "^6.3.13",
"babel-plugin-transform-es2015-spread": "^6.3.13",
"babel-plugin-transform-es2015-template-literals": "^6.3.13",
"babel-plugin-transform-object-rest-spread": "^6.3.13",
"babel-preset-react": "^6.5.0"
"babel-plugin-transform-runtime": "^6.9.0",
"babel-plugin-react-server": "^0.0.1",
"babel-preset-es2015": "^6.5.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-0": "^6.5.0"
},
"devDependencies": {
"rimraf": "^2.5.2"
Expand Down
1 change: 0 additions & 1 deletion packages/generator-react-server/generators/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ module.exports = yeoman.Base.extend({
});

let files = [
'gulpfile.js',
'pages/hello-world.js',
'components/hello-world.js',
'package.json',
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
"description": "A react-server instance",
"main": "HelloWorld.js",
"scripts": {
"compile": "gulp",
"start": "react-server-cli --port 3010 --js-port 3011 --routes build/routes.js",
"start": "react-server-cli --port 3010 --js-port 3011",
"test": "xo && nsp check && ava test.js"
},
"license": "Apache-2.0",
Expand All @@ -22,11 +21,9 @@
},
"devDependencies": {
"ava": "^0.15.1",
"babel-preset-react-server": "^0.2.0",
"babel-preset-react-server": "^0.3.0",
"eslint-config-xo-react": "^0.7.0",
"eslint-plugin-react": "^5.1.1",
"gulp": "^3.9.1",
"gulp-babel": "^6.1.2",
"nsp": "^2.3.3",
"react-server-gulp-module-tagger": "^0.2.6",
"xo": "^0.15.1"
Expand Down
16 changes: 0 additions & 16 deletions packages/generator-react-server/generators/app/templates/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import test from 'ava';
let rs;

test.before('start the server', async () => {
const stdout = await exec('npm run compile');
console.log(stdout);
rs = cp.spawn('npm', ['start']);
rs.stderr.on('data', data => console.error(`ERR: ${data}`));
await sleep(10000);
Expand All @@ -20,20 +18,6 @@ test.after.always('shut down the server', async () => {
rs.kill('SIGHUP');
});

// runs a command asynchronously
function exec(cmd, opts = {maxBuffer: 1024 * 100000}) {
return new Promise((resolve, reject) => {
cp.exec(cmd, opts, (error, stdout, stderr) => {
if (error) {
console.error(stderr);
reject(error);
return;
}
resolve(stdout);
});
});
}

// gets the response code for an http request
function getResponseCode(url) {
return new Promise((resolve, reject) => {
Expand Down
Loading

0 comments on commit a1fac00

Please sign in to comment.