1
1
mirror of https://github.com/c8r/x0.git synced 2024-09-11 13:45:52 +03:00
Document & develop React components without breaking a sweat
Go to file
2017-10-19 14:17:56 -06:00
bin Add a publish option 2017-10-19 11:56:53 -06:00
docs Adjust static template 2017-10-10 20:12:11 -04:00
examples Edit readme 2017-10-07 16:01:22 -04:00
lib Merge pull request #4 from c8r/proxy 2017-10-17 20:36:08 -06:00
test Only remove output dir if it exists 2017-10-19 14:17:56 -06:00
.gitignore Only remove output dir if it exists 2017-10-19 14:17:56 -06:00
.npmrc Experimenting with Head component 2017-10-07 09:38:46 -04:00
index.js Organize modules 2017-09-13 16:21:39 -04:00
package.json 2.0.0-8 2017-10-19 12:08:38 -06:00
README.md Edit docs 2017-10-08 09:34:16 -04:00

x0

Zero-config React development environment and static site generator

https://compositor.io/x0

npm install @compositor/x0

Features

  • Hot-loading development environment
  • Works with virtually any React component*
  • No convoluted APIs
  • Renders static HTML
  • Renders JS bundles
  • Use any CSS-in-JS library
  • Routing with react-router
  • Async data fetching

* Components cannot rely on bundler features like webpack loaders

Isolated development environment

x0 dev src/App.js

Options:

  -o --open   Open dev server in default browser
  -p --port   Set custom port for dev server
x0 dev src/App.js -op 8080

Static Render

Render static HTML and client-side bundle

x0 build src/App.js --out-dir site

Render static HTML without bundle

x0 build src/App.js --out-dir site --static

Options

  -d --out-dir    Directory to save index.html and bundle.js to
  -s --static     Only render static HTML (no client-side JS)

Fetching Data

Use the getInitialProps static method to fetch data for static rendering. This method was inspired by Next.js but only works for static rendering.

const App = props => (
  <h1>Hello {props.data}</h1>
)

App.getInitialProps = async ({
  Component,
  html,
  pathname
}) => {
  const fetch = require('isomorphic-fetch')
  const res = await fetch('http://example.com/data')
  const data = await res.json()

  return { data }
}

CSS-in-JS

Use the getInitialProps static method to precompile CSS from css-in-js libraries such as styled-components

// styled-components
import React from 'react'
import styled from 'styled-components'

const Heading = styled.h1`
  color: tomato;
`

const App = props => [
  props.styles && (
    <head
      dangerouslySetInnerHTML={{
        __html: props.styles
      }}
    />
  ),
  <div>
    <Heading>Hello</Heading>
  </div>
]

App.getInitialProps = async ({
  Component,
  props
}) => {
  const { ServerStyleSheet } = require('styled-components')
  const sheet = new ServerStyleSheet()
  sheet.collectStyles(<Component {...props} />)
  const styles = sheet.getStyleTags()
  return { styles }
}
// CXS
import React from 'react'
import cxs from 'cxs/component'

const Heading = cxs('h1')({
  color: 'tomato'
})

const App = props => (
  <div>
    <style
      dangerouslySetInnerHTML={{
        __html: props.css
      }}
    />
    <Heading>Hello</Heading>
  </div>
)

App.getInitialProps = async () => {
  const css = cxs.css()
  return { css }
}

Head content

Head elements such as <title>, <meta>, and <style> can be rendered at the beginning of a component. Browsers should handle this correctly since the <head> and <body> elements are optional in HTML 5.

const App = props => (
  <div>
    <title>Hello x0</title>
    <style dangerouslySetInnerHTML={{
      __html: 'body{font-family:-apple-system,BlinkMacSystemFont,sans-serif}'
    }} />
    <h1>Hello x0</h1>
  </div>
)

Returning an array of elements also works.

const App = props => [
  <title>Hello</title>,
  <div>
    <h1>Hello</h1>
  </div>
]

Configuration

Default props can be passed to x0 in a package.json field named x0.

"x0": {
  "title": "Hello",
  "count": 0
}

Routing

To render multiple pages and use routing, add a routes array to the package.json configuration object.

"x0": {
  "routes": [
    "/",
    "/about"
  ]
}
x0 static src/App.js --out-dir site

For easier integration with react-router, use the x0 Router component, which handles universal rendering.

import React from 'react'
import Router from '@compositor/x0/Router'
import { Route, Link } from 'react-router-dom'
import Home from './Home'
import About from './About'

const App = props => (
  <Router
    basename={props.basename}
    location={props.pathname}>
    <nav>
      <Link to='/'>Home</Link>
      <Link to='/about'>About</Link>
    </nav>
    <Route
      exact
      path='/'
      render={() => <Home {...props} />}
    />
    <Route
      path='/about'
      render={() => <About {...props} />}
    />
  </Router>
)

MIT License