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 babel plugin for module tagging #280

Closed
wants to merge 12 commits into from
Closed
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@

## v0.3.2 (2016-06-13)

#### Bug fix
* `react-server`
* [#268](https://github.com/redfin/react-server/pull/268) Include URL fragment in history navigation stack pathnames. ([@gigabo](https://github.com/gigabo))

#### Enhancement
* `react-server-examples`
* [#222](https://github.com/redfin/react-server/pull/222) Add bike share example. ([@doug-wade](https://github.com/doug-wade))

#### Performance
* `react-server`
* [#274](https://github.com/redfin/react-server/pull/274) Clear failsafe timeouts on route/render success. ([@gigabo](https://github.com/gigabo))

#### Commiters: 3
- Bo Borgerson ([gigabo](https://github.com/gigabo))
- Carey Spies ([careylin](https://github.com/careylin))
- Douglas Wade ([doug-wade](https://github.com/doug-wade))

## v0.3.1 (2016-06-03)

#### Bug fix
Expand Down
49 changes: 47 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,57 @@ transitions between pages in the browser.
#### Just getting started with `react-server`?

The _easiest_ way to get started is with our [yeoman
generator](packages/generator-react-server).
generator](packages/generator-react-server):

```bash
# install yeoman
npm install -g yo

# install the react-server generator
npm install -g generator-react-server

# make a new react-server project in the CURRENT directory
yo react-server

# compile and run the new app
npm run compile
npm run start
# go to http://localhost:3010
```

That hooks you up with [`react-server-cli`](packages/react-server-cli), which
will take care of the _server_ part and get you up and running right away.

Once you're hungry for more dig into [the docs](docs/) and
#### Why `react-server`?

One of the great things about React is its support for server-side rendering,
which can make sites show up faster for users and play better with search engine
bots.

However, when you actually try to use React for server-side rendering, you
quickly run into a bunch of practical problems, such as:

- How should I load data on the server for my components?
- How do I ensure that the client and the server load the same data and generate
the same HTML markup?
- How do I write code that can be both generated server-side and be part of a
single-page application (SPA)?
- How should I optimize the delivery of my JavaScript and CSS?
- How do I find out about and follow performance best practices?
- How do I ensure that my site is streamed to the browser as quickly as humanly
possible?
- How can I make my app resilient when my backend has high latency spikes?

`react-server` is a framework designed to make universal (neé isomorphic) React
easier to write, providing standard answers for these questions and more. When
you write your app for `react-server`, you concentrate on your React components,
and `react-server` takes care of everything else that's needed to run and deploy
real React server-rendered apps. Under the hood, `react-server` is doing a bunch
of clever optimizations, many borrowed from the ideas behind [Facebook's Big Pipe](https://www.facebook.com/notes/facebook-engineering/bigpipe-pipelining-web-pages-for-high-performance/389414033919/),
to make sure that your site shows up as quickly as humanly possible
for your users.

Once you're hungry for more, dig into [the docs](docs/) and
[`react-server`](packages/react-server) itself.
** **

Expand Down
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).
4 changes: 2 additions & 2 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"lerna": "2.0.0-beta.14",
"version": "0.3.1",
"lerna": "2.0.0-beta.18",
"version": "0.3.2",
"changelog": {
"repo": "redfin/react-server",
"labels": {
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"bootstrap": "npm i; lerna bootstrap",
"test": "lerna run test",
"clean": "rimraf lerna-debug.log && lerna run clean",
"nuke": "rm -r node_modules; for d in packages/*/node_modules; do echo $d; rm -r $d; done"
"nuke": "lerna clean && rm -r node_modules"
},
"devDependencies": {
"babel-plugin-react-require": "^2.1.0",
Expand Down Expand Up @@ -36,6 +36,7 @@
"jasmine": "2.3.1",
"jsdom": "5.6.1",
"jsx-loader": "0.12.2",
"lerna": "2.0.0-beta.18",
"minimist": "1.1.0",
"mkdirp": "^0.5.1",
"path-to-regexp": "1.0.1",
Expand All @@ -45,7 +46,6 @@
"rimraf": "^2.5.2",
"superagent": "1.2.0",
"webpack": "1.4.13",
"zombie": "4.1.0",
"lerna": "2.0.0-beta.14"
"zombie": "4.1.0"
}
}
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));
});
});
});
Loading