├── docs
├── .nojekyll
├── CNAME
├── package.json
├── plugins.md
├── guide
│ └── getting-started.md
├── index.html
├── api.md
└── README.md
├── examples
├── sample
│ ├── style
│ │ ├── home.css
│ │ └── index.less
│ ├── utils.js
│ ├── serlina.config.js
│ ├── pages
│ │ ├── _404.js
│ │ ├── user
│ │ │ └── list.js
│ │ ├── counter.js
│ │ ├── foo.tsx
│ │ └── page2.js
│ ├── tsconfig.json
│ ├── babel.config.js
│ ├── components
│ │ └── PrimaryButton.js
│ └── package.json
├── serlina-koa
│ ├── pages
│ │ └── page1.js
│ ├── package.json
│ └── index.js
├── react-router
│ ├── views
│ │ └── Home
│ │ │ ├── about.js
│ │ │ ├── index.js
│ │ │ └── posts.js
│ ├── apolloClient.js
│ ├── index.js
│ ├── package.json
│ └── pages
│ │ └── home.js
├── css-in-js
│ ├── pages
│ │ └── page1.js
│ └── package.json
└── apollo
│ ├── package.json
│ └── pages
│ └── home.js
├── packages
├── serlina-serve
│ ├── .gitignore
│ ├── __test__
│ │ ├── fixtures
│ │ │ └── pages
│ │ │ │ └── page1.js
│ │ └── index.test.js
│ ├── bin
│ │ └── serlina-serve
│ ├── commands
│ │ ├── dev.js
│ │ └── start.js
│ ├── README.md
│ ├── index.js
│ └── package.json
├── serlina
│ ├── head.js
│ ├── test
│ │ └── unit
│ │ │ ├── fixtures
│ │ │ └── sample
│ │ │ │ ├── styles
│ │ │ │ └── index.css
│ │ │ │ └── pages
│ │ │ │ ├── page1.js
│ │ │ │ ├── user
│ │ │ │ └── list.js
│ │ │ │ └── page2.js
│ │ │ ├── __snapshots__
│ │ │ └── index.test.js.snap
│ │ │ └── index.test.js
│ ├── lib
│ │ ├── index.ts
│ │ ├── components
│ │ │ ├── _404.tsx
│ │ │ ├── Head.ts
│ │ │ └── Document.tsx
│ │ ├── client
│ │ │ ├── common.ts
│ │ │ ├── App.tsx
│ │ │ └── render.tsx
│ │ ├── utils
│ │ │ └── eventbus.ts
│ │ ├── config
│ │ │ ├── serlina-loader.ts
│ │ │ └── webpack.config.ts
│ │ ├── commands
│ │ │ └── build.ts
│ │ └── serlina.ts
│ ├── bin
│ │ └── serlina
│ ├── tsconfig.json
│ ├── babel.config.js
│ └── package.json
├── serlina-apollo
│ ├── src
│ │ ├── index.ts
│ │ └── withApollo.tsx
│ ├── tsconfig.json
│ ├── package.json
│ └── README.md
├── serlina-react-router
│ ├── src
│ │ ├── index.ts
│ │ └── withRouter.tsx
│ ├── tsconfig.json
│ ├── package.json
│ └── README.md
└── serlina-koa
│ ├── package.json
│ ├── index.js
│ └── README.md
├── lerna.json
├── .gitignore
├── package.json
├── LICENSE
├── .circleci
└── config.yml
└── README.md
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | serlina.js.org
--------------------------------------------------------------------------------
/examples/sample/style/home.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: black;
3 | }
--------------------------------------------------------------------------------
/examples/sample/style/index.less:
--------------------------------------------------------------------------------
1 | body {
2 | background: red;
3 | }
--------------------------------------------------------------------------------
/packages/serlina-serve/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | .serlina
4 |
--------------------------------------------------------------------------------
/packages/serlina/head.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./dist/components/Head')
2 |
--------------------------------------------------------------------------------
/packages/serlina/test/unit/fixtures/sample/styles/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: red;
3 | }
--------------------------------------------------------------------------------
/packages/serlina/lib/index.ts:
--------------------------------------------------------------------------------
1 | import Serlina from './serlina'
2 |
3 | export {
4 | Serlina,
5 | }
6 |
--------------------------------------------------------------------------------
/examples/sample/utils.js:
--------------------------------------------------------------------------------
1 | export const foo = 'ba??!?'
2 |
3 | export default function test () {
4 | return 'test'
5 | }
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "packages": [
3 | "examples/*",
4 | "packages/*"
5 | ],
6 | "version": "0.0.0"
7 | }
8 |
--------------------------------------------------------------------------------
/packages/serlina-apollo/src/index.ts:
--------------------------------------------------------------------------------
1 | import withApollo from './withApollo'
2 |
3 | export {
4 | withApollo
5 | }
6 |
--------------------------------------------------------------------------------
/examples/sample/serlina.config.js:
--------------------------------------------------------------------------------
1 | const { withAntd } = require('serlina-plugin-antd')
2 |
3 | module.exports = withAntd()
4 |
--------------------------------------------------------------------------------
/packages/serlina-react-router/src/index.ts:
--------------------------------------------------------------------------------
1 | import withRouter from './withRouter'
2 |
3 | export {
4 | withRouter
5 | }
6 |
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "start": "docute ."
4 | },
5 | "devDependencies": {
6 | "docute": "^3.4.12"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/examples/sample/pages/_404.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | export default () => {
4 | return (
5 |
404!
6 | )
7 | }
8 |
--------------------------------------------------------------------------------
/examples/sample/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "jsx": "react",
5 | "target": "es6"
6 | }
7 | }
--------------------------------------------------------------------------------
/examples/sample/pages/user/list.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | export default () => {
4 | return (
5 | User List?
6 | )
7 | }
--------------------------------------------------------------------------------
/packages/serlina-serve/__test__/fixtures/pages/page1.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | export default () => {
4 | return Page1
5 | }
6 |
--------------------------------------------------------------------------------
/packages/serlina/test/unit/fixtures/sample/pages/page1.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | export default () => {
4 | return Page1
5 | }
6 |
--------------------------------------------------------------------------------
/packages/serlina/test/unit/fixtures/sample/pages/user/list.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | export default () => {
4 | return User List
5 | }
6 |
--------------------------------------------------------------------------------
/packages/serlina/lib/components/_404.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | module.exports = () => {
4 | return (
5 | Page not found
6 | )
7 | }
8 |
--------------------------------------------------------------------------------
/examples/serlina-koa/pages/page1.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | export default () => {
4 | return (
5 |
6 | Serlina Koa
7 |
8 | )
9 | }
--------------------------------------------------------------------------------
/examples/sample/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (api) {
2 | api.cache(true)
3 |
4 | return {
5 | extends: require.resolve('serlina/babel.config.js')
6 | }
7 | }
--------------------------------------------------------------------------------
/examples/sample/components/PrimaryButton.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | export default (props) => {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/packages/serlina/bin/serlina:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const yargs = require('yargs')
4 |
5 | yargs
6 | .commandDir('../dist/commands')
7 | .demandCommand()
8 | .help()
9 | .argv
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | yarn.lock
4 | test/sample/public
5 | package-lock.json
6 | .serlina
7 | dist
8 | packages/serlina-react-router/lib
9 | packages/serlina-apollo/lib
10 | .awcache
--------------------------------------------------------------------------------
/packages/serlina-serve/bin/serlina-serve:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const yargs = require('yargs')
4 |
5 | yargs
6 | .commandDir('../commands')
7 | .demandCommand()
8 | .help()
9 | .argv
10 |
--------------------------------------------------------------------------------
/packages/serlina/lib/client/common.ts:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import * as ReactDOM from 'react-dom'
3 |
4 | // @ts-ignore
5 | global.React = React
6 | // @ts-ignore
7 | global.ReactDOM = ReactDOM
8 |
--------------------------------------------------------------------------------
/examples/react-router/views/Home/about.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | export default class About extends React.Component {
4 | render () {
5 | return (
6 |
7 | About
8 |
9 | )
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/examples/react-router/views/Home/index.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | export default class Index extends React.Component {
4 | render () {
5 | return (
6 |
7 | Home
8 |
9 | )
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/serlina/lib/components/Head.ts:
--------------------------------------------------------------------------------
1 | let h;
2 |
3 | // @ts-ignore
4 | if (global.Helmet) {
5 | // @ts-ignore
6 | h = global.Helmet
7 | } else {
8 | const { Helmet } = require('react-helmet')
9 | h = Helmet
10 | }
11 |
12 | export default h
--------------------------------------------------------------------------------
/examples/serlina-koa/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "serlina-koa-example",
3 | "scripts": {
4 | "start": "node index.js"
5 | },
6 | "dependencies": {
7 | "react": "^16",
8 | "react-dom": "^16",
9 | "serlina": "^1",
10 | "serlina-koa": "^1"
11 | }
12 | }
--------------------------------------------------------------------------------
/packages/serlina-koa/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "serlina-koa",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "start": "node example"
6 | },
7 | "dependencies": {
8 | "path-to-regexp": "^2.2.1"
9 | },
10 | "peerDependencies": {
11 | "serlina": "^1"
12 | }
13 | }
--------------------------------------------------------------------------------
/packages/serlina/lib/client/App.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | declare var window: any
4 |
5 | const Component = window.__serlina.default
6 |
7 | const App = () => {
8 | return
9 | }
10 |
11 | export default App
12 |
--------------------------------------------------------------------------------
/packages/serlina/lib/client/render.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import { hydrate } from 'react-dom'
3 |
4 | import App from './App'
5 | declare var window: any
6 |
7 | if (window.__serlina) {
8 | hydrate(, document.querySelector('#app'))
9 | }
10 |
11 | export default App
12 |
--------------------------------------------------------------------------------
/examples/css-in-js/pages/page1.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | import { css } from 'emotion'
4 |
5 | const styles = css`
6 | background-color: red;
7 | color: white;
8 | `
9 |
10 | export default () => {
11 | return (
12 |
13 | Page1
14 |
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/examples/css-in-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "css-in-js-sample",
3 | "scripts": {
4 | "start": "serlina-serve dev"
5 | },
6 | "dependencies": {
7 | "emotion": "^9.2.6",
8 | "react": "^16.4.2",
9 | "react-dom": "^16.4.2"
10 | },
11 | "devDependencies": {
12 | "serlina-serve": "^0.1.0"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/packages/serlina-apollo/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "jsx": "react",
6 | "rootDir": "src",
7 | "strictNullChecks": true,
8 | "outDir": "lib",
9 | "lib": [
10 | "dom",
11 | "es2015",
12 | "esnext.asynciterable"
13 | ]
14 | }
15 | }
--------------------------------------------------------------------------------
/packages/serlina-react-router/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "jsx": "react",
6 | "rootDir": "src",
7 | "strictNullChecks": true,
8 | "outDir": "lib",
9 | "lib": [
10 | "dom",
11 | "es2015",
12 | "esnext.asynciterable"
13 | ]
14 | }
15 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "test": "jest",
4 | "bootstrap": "lerna bootstrap",
5 | "clean": "lerna clean"
6 | },
7 | "devDependencies": {
8 | "jest": "^23.5.0",
9 | "lerna": "^3.0.3",
10 | "power-assert": "^1.6.0"
11 | },
12 | "jest": {
13 | "testURL": "http://localhost/",
14 | "testEnvironment": "node"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/packages/serlina/test/unit/fixtures/sample/pages/page2.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import '../styles/index.css'
3 |
4 | export default class Page2 extends React.Component {
5 |
6 | static async getInitialProps() {
7 | return {
8 | foo: 'foo'
9 | }
10 | }
11 |
12 | render () {
13 | return Page2 - {this.props.foo}
14 | }
15 | }
--------------------------------------------------------------------------------
/packages/serlina/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "module": "commonjs",
5 | "outDir": "dist",
6 | "jsx": "react",
7 | "moduleResolution": "node",
8 | "declaration": true,
9 | "strictNullChecks": true
10 | },
11 | "include": [
12 | "lib"
13 | ],
14 | "exclude": [
15 | "node_modules"
16 | ]
17 | }
--------------------------------------------------------------------------------
/packages/serlina/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (api) {
2 |
3 | api.cache(true)
4 |
5 | const presets = [
6 | [require.resolve('@babel/preset-env'), {
7 | modules: false
8 | }], require.resolve('@babel/preset-react')
9 | ]
10 |
11 | const plugins = [
12 | require.resolve('@babel/plugin-proposal-class-properties')
13 | ]
14 |
15 | return {
16 | presets,
17 | plugins
18 | }
19 | }
--------------------------------------------------------------------------------
/examples/sample/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample",
3 | "scripts": {
4 | "test": "serlina-serve dev",
5 | "build": "serlina build . --publicPath http://localhost:1024/"
6 | },
7 | "dependencies": {
8 | "antd": "^3.7.3",
9 | "typescript": "^3",
10 | "react": "^16.4.2",
11 | "react-dom": "^16.4.2",
12 | "serlina": "^1",
13 | "serlina-plugin-antd": "^0.2",
14 | "serlina-serve": "^1"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/packages/serlina/lib/utils/eventbus.ts:
--------------------------------------------------------------------------------
1 | export default class EventBus {
2 |
3 | handlers = {};
4 |
5 | on (eventName: string, fn) {
6 | this.handlers[eventName] = this.handlers[eventName] || []
7 | this.handlers[eventName].push(fn)
8 | }
9 |
10 | emit (eventName: string, payload?: any) {
11 | if (this.handlers[eventName]) {
12 | this.handlers[eventName].forEach(fn => {
13 | fn(payload)
14 | })
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/docs/plugins.md:
--------------------------------------------------------------------------------
1 | # Plugins
2 |
3 | A Serlina plugin means a reusable Serlina config.
4 |
5 | ## Use a plugin
6 |
7 | For example, an `serlina-plugin-antd` includes some webpack config for using ant.design:
8 |
9 | ```js
10 | // serlina.config.js
11 |
12 | const { withAntd } = require('serlina-plugin-antd')
13 |
14 | module.exports = withAntd()
15 | ```
16 |
17 | ### Official plugins
18 |
19 | Official plugins are managed on https://github.com/serlina-community/serlina-plugins
--------------------------------------------------------------------------------
/packages/serlina/lib/config/serlina-loader.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path'
2 | import { getOptions } from 'loader-utils'
3 |
4 | function Loader (content, map, meta) {
5 | const options = getOptions(this)
6 | if (this.context.match(path.resolve(options.baseDir, './pages'))) {
7 | return `
8 | console.log('start here');
9 | ${content};
10 | console.log(module)
11 | `
12 | } else {
13 | return content
14 | }
15 | }
16 | export default Loader
17 |
--------------------------------------------------------------------------------
/examples/react-router/apolloClient.js:
--------------------------------------------------------------------------------
1 | import { ApolloClient } from 'apollo-client'
2 | import { InMemoryCache } from "apollo-cache-inmemory"
3 | import { createHttpLink } from 'apollo-link-http'
4 | import * as fetch from 'isomorphic-fetch'
5 |
6 | export default (initialState = {}) => {
7 | return new ApolloClient({
8 | ssrMode: true,
9 | cache: new InMemoryCache().restore(initialState),
10 | link: createHttpLink({
11 | uri: 'https://w5v4jr97kz.lp.gql.zone/graphql',
12 | fetch
13 | })
14 | })
15 | }
16 |
--------------------------------------------------------------------------------
/packages/serlina-react-router/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "serlina-react-router",
3 | "version": "1.0.0",
4 | "main": "lib/index.js",
5 | "scripts": {
6 | "start": "tsc --watch",
7 | "build": "tsc",
8 | "prepublish": "npm run build"
9 | },
10 | "dependencies": {
11 | },
12 | "peerDependencies": {
13 | "react-router-dom": "^4"
14 | },
15 | "devDependencies": {
16 | "@types/react": "^16.4.10",
17 | "react-router-dom": "^4.3.1",
18 | "react": "^16.4.2",
19 | "typescript": "^3.0.1"
20 | }
21 | }
--------------------------------------------------------------------------------
/packages/serlina-apollo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "serlina-apollo",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "start": "tsc --watch"
6 | },
7 | "main": "lib/index.js",
8 | "dependencies": {
9 | },
10 | "peerDependencies": {
11 | "serlina": "^1"
12 | },
13 | "devDependencies": {
14 | "react-dom": "^16.4.2",
15 | "apollo-client": "^2.3.8",
16 | "react-apollo": "^2.1.11",
17 | "typescript": "^3",
18 | "graphql": "^0.13.2",
19 | "react": "^16.4.2",
20 | "@types/react": "^16"
21 | }
22 | }
--------------------------------------------------------------------------------
/examples/apollo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "apollo-example",
3 | "scripts": {
4 | "start": "serlina-serve dev"
5 | },
6 | "devDependencies": {
7 | "react": "^16.4.2",
8 | "react-dom": "^16.4.2",
9 | "graphql": "^0.13.2",
10 | "serlina-serve": "^0.1.1",
11 | "serlina-apollo": "^0.1",
12 | "apollo-cache-inmemory": "^1.2.7",
13 | "react-apollo": "^2.1.11",
14 | "apollo-client": "^2.3.8",
15 | "graphql-tag": "^2.9.2",
16 | "apollo-link-http": "^1.5.4",
17 | "isomorphic-fetch": "^2.2.1"
18 | }
19 | }
--------------------------------------------------------------------------------
/examples/serlina-koa/index.js:
--------------------------------------------------------------------------------
1 | const Koa = require('koa')
2 | const {Serlina} = require('serlina')
3 | const path = require('path')
4 |
5 | // init Serlina
6 | const serlina = new Serlina({
7 | baseDir: path.resolve(__dirname, './')
8 | })
9 |
10 | const serlinaKoa = require('serlina-koa')
11 |
12 | const app = new Koa()
13 |
14 | serlina.prepare().then(() => {
15 |
16 | // map the url
17 | app.use(serlinaKoa({
18 | serlina,
19 | mapAll: true
20 | }))
21 |
22 | app.listen(3001, () => {
23 | console.log('Started on http://localhost:3001')
24 | })
25 |
26 | })
--------------------------------------------------------------------------------
/examples/react-router/index.js:
--------------------------------------------------------------------------------
1 | const Koa = require('koa')
2 | const {Serlina} = require('serlina')
3 | const path = require('path')
4 | const Router = require('koa-router')
5 |
6 | const serlina = new Serlina({
7 | baseDir: path.resolve(__dirname)
8 | })
9 |
10 | serlina.prepare().then(() => {
11 | const app = new Koa()
12 | const router = new Router()
13 |
14 | router.get('/home*', async (ctx) => {
15 | ctx.body = (await serlina.render('home', { ctx })).body
16 | })
17 |
18 | app.use(router.routes())
19 |
20 | app.listen(3001, () => {
21 | console.log('listen on 3001')
22 | })
23 | })
--------------------------------------------------------------------------------
/examples/sample/pages/counter.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | export default class Counter extends React.Component {
4 |
5 | state = {
6 | count: 0
7 | }
8 |
9 | incr = () => {
10 | this.setState({ count: this.state.count + 1 })
11 | }
12 |
13 | decr = () => {
14 | this.setState({ count: this.state.count - 1 })
15 | }
16 |
17 |
18 | render () {
19 | return (
20 |
21 |
Hot Reload Counter
22 | {this.state.count}
23 |
24 |
25 |
26 | )
27 | }
28 | }
--------------------------------------------------------------------------------
/examples/sample/pages/foo.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | export default class Counter extends React.Component {
4 |
5 | state = {
6 | count: 0 as number
7 | }
8 |
9 | incr = () => {
10 | this.setState({ count: this.state.count + 1 })
11 | }
12 |
13 | decr = () => {
14 | this.setState({ count: this.state.count - 1 })
15 | }
16 |
17 | render () {
18 | return (
19 |
20 |
Hot Reload Counter
21 | {this.state.count}
22 |
23 |
24 |
25 | )
26 | }
27 | }
--------------------------------------------------------------------------------
/packages/serlina/lib/commands/build.ts:
--------------------------------------------------------------------------------
1 | import Serlina from '../serlina'
2 | import * as path from 'path'
3 |
4 | exports.command = 'build '
5 |
6 | exports.builder = {
7 | 'baseDir': {
8 | description: 'baseDir. Relative to process.cwd()'
9 | },
10 | 'outputPath': {
11 | description: 'assets file output path.'
12 | },
13 | 'publicPath': {
14 | description: 'publicPath in webpack. Set it if you use CDN'
15 | }
16 | }
17 |
18 | exports.handler = argv => {
19 |
20 | const app = new Serlina({
21 | ...argv,
22 | dev: false,
23 | baseDir: path.resolve(process.cwd(), argv.baseDir)
24 | })
25 |
26 | const compiler = app.build()
27 | compiler.run()
28 | }
--------------------------------------------------------------------------------
/examples/react-router/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-router-sample",
3 | "scripts": {
4 | "start": "node index.js"
5 | },
6 | "dependencies": {
7 | "serlina-react-router": "^0.1.0",
8 | "react-router-dom": "^4.3.1",
9 | "react": "^16.4.2",
10 | "react-dom": "^16.4.2"
11 | },
12 | "devDependencies": {
13 | "serlina": "^1",
14 | "koa": "^2.5.2",
15 | "koa-router": "^7.4.0",
16 | "graphql": "^0.13.2",
17 | "serlina-apollo": "^0.1",
18 | "apollo-cache-inmemory": "^1.2.7",
19 | "react-apollo": "^2.1.11",
20 | "apollo-client": "^2.3.8",
21 | "graphql-tag": "^2.9.2",
22 | "apollo-link-http": "^1.5.4",
23 | "isomorphic-fetch": "^2.2.1"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/serlina-serve/commands/dev.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const Serve = require('..')
3 |
4 | exports.command = 'dev [baseDir]'
5 | exports.description = 'Start server in dev mode'
6 |
7 | exports.builder = {
8 | baseDir: {
9 | default: '.'
10 | },
11 | port: {
12 | default: 3001,
13 | alias: 'p'
14 | }
15 | }
16 |
17 | exports.handler = argv => {
18 | const {
19 | baseDir,
20 | port
21 | } = argv
22 |
23 | const serve = new Serve({
24 | baseDir: path.resolve(process.cwd(), baseDir),
25 | publicPath: '/public/'
26 | })
27 |
28 | serve.serlina.prepare().then(() => {
29 | serve.app.listen(port, () => {
30 | console.log('Running at http://localhost:' + port)
31 | })
32 | })
33 | }
--------------------------------------------------------------------------------
/packages/serlina-serve/commands/start.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const Serve = require('..')
3 |
4 | exports.command = 'start [baseDir]'
5 | exports.description = 'Start server in prod mode'
6 |
7 | exports.builder = {
8 | baseDir: {
9 | default: '.'
10 | },
11 | port: {
12 | default: 3001,
13 | alias: 'p'
14 | }
15 | }
16 |
17 | exports.handler = argv => {
18 | const {
19 | baseDir,
20 | port
21 | } = argv
22 |
23 | const serve = new Serve({
24 | baseDir: path.resolve(process.cwd(), baseDir),
25 | dev: false,
26 | publicPath: '/public/'
27 | })
28 |
29 | serve.serlina.prepare().then(() => {
30 | serve.app.listen(port, () => {
31 | console.log('Running at http://localhost:' + port)
32 | })
33 | })
34 | }
--------------------------------------------------------------------------------
/packages/serlina-serve/README.md:
--------------------------------------------------------------------------------
1 | # serlina-serve
2 |
3 | [](https://npm.im/serlina-serve)
4 | [](https://npm.im/serlina-serve)
5 | [](https://circleci.com/gh/djyde/serlina)
6 |
7 | [🚨 WIP] A simple Serlina web server based on [serlina-koa](../serlina-koa)
8 |
9 | ## Usage
10 |
11 | serlina-serve will map all pages in `/pages` to route (files as router).
12 |
13 | ```
14 | npm i react react-dom serlina-serve --save
15 | ```
16 |
17 | ```json
18 | {
19 | "scripts": {
20 | "dev": "serlina-serve dev",
21 | "start": "serlina-serve start"
22 | }
23 | }
24 | ```
25 |
26 | # License
27 |
28 | MIT License
29 |
--------------------------------------------------------------------------------
/examples/react-router/views/Home/posts.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import { Query } from 'react-apollo'
3 | import * as gql from 'graphql-tag'
4 |
5 | export default () => {
6 | return (
7 |
8 |
16 | {({ loading, data }) => {
17 | if (loading) {
18 | return "loading"
19 | } else {
20 | const posts = data.posts || []
21 | return (
22 |
23 | {posts.map(post => {
24 | return
{post.title}
25 | })}
26 |
27 | )
28 | }
29 | }}
30 |
31 |
32 | )
33 | }
--------------------------------------------------------------------------------
/examples/sample/pages/page2.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import '../style/index.less'
3 | import Head from 'serlina/head'
4 | import {
5 | Button
6 | } from 'antd'
7 | import PrimaryButton from '../components/PrimaryButton'
8 | import * as utils from '../utils'
9 |
10 | class Page2 extends React.Component {
11 |
12 | static async getInitialProps ({ req }) {
13 | return {
14 | foo: 'foo??!'
15 | }
16 | }
17 |
18 | render () {
19 | return (
20 |
21 |
22 |
Page2
23 |
24 |
25 |
26 |
Hi?
27 | {this.props.foo}
28 |
29 | )
30 | }
31 | }
32 |
33 | export default Page2
34 |
--------------------------------------------------------------------------------
/packages/serlina-serve/__test__/index.test.js:
--------------------------------------------------------------------------------
1 | const Serve = require('../')
2 | const path = require('path')
3 | const supertest = require('supertest')
4 |
5 | describe('serlina-serve', () => {
6 | let request
7 |
8 |
9 | beforeAll(() => {
10 | return new Promise((res, rej) => {
11 | const serve = new Serve({
12 | baseDir: path.resolve(__dirname, './fixtures'),
13 | __testing: true
14 | })
15 |
16 | serve.serlina.prepare().then(() => {
17 | const server = serve.app.listen(3001, () => {
18 | request = supertest(server)
19 |
20 | res()
21 | })
22 | })
23 | })
24 | })
25 |
26 | test('render page', async () => {
27 | const res = await request.get('/page1')
28 |
29 | expect(res.text.startsWith('')).toBeTruthy()
30 | })
31 | })
--------------------------------------------------------------------------------
/packages/serlina-koa/index.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert')
2 | const pathToReg = require('path-to-regexp')
3 |
4 | const handler = (options = {}) => {
5 | return async ctx => {
6 | const {
7 | serlina,
8 | map,
9 | payload
10 | } = options
11 |
12 | assert(serlina, 'Serlina instance is required!')
13 |
14 | const injected = Object.assign({}, { ctx }, payload || {})
15 |
16 | let renderedPath;
17 |
18 | if (map) {
19 | Object.keys(map).forEach(path => {
20 | const re = pathToReg(path)
21 | if (ctx.path.match(re)) {
22 | renderedPath = path
23 | }
24 | })
25 |
26 | if (renderedPath) {
27 | const rendered = await serlina.render(renderedPath, injected)
28 | ctx.body = rendered.body
29 | }
30 | }
31 | }
32 | }
33 |
34 | module.exports = handler
--------------------------------------------------------------------------------
/packages/serlina-serve/index.js:
--------------------------------------------------------------------------------
1 | const Koa = require('koa')
2 | const { Serlina } = require('serlina')
3 | const serlinaKoa = require('serlina-koa')
4 | const path = require('path')
5 | const fs = require('fs')
6 | const glob = require('glob')
7 |
8 | class Serve {
9 |
10 | constructor(options) {
11 |
12 | const app = new Koa()
13 |
14 | const serlina = new Serlina(options)
15 |
16 | const {
17 | baseDir
18 | } = options
19 |
20 | const map = {}
21 |
22 | glob.sync('**/*.*', {
23 | cwd: path.resolve(baseDir, './pages')
24 | }).map(filename => filename.split('.')[0]).forEach(page => {
25 | map['/' + page] = page
26 | })
27 |
28 | app.use(serlinaKoa({
29 | serlina,
30 | map
31 | }))
32 |
33 | this.serlina = serlina
34 | this.app = app
35 | }
36 | }
37 |
38 | module.exports = Serve
39 |
--------------------------------------------------------------------------------
/examples/react-router/pages/home.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import { withRouter } from 'serlina-react-router'
3 | import { withApollo } from 'serlina-apollo'
4 | import { Route, Switch } from 'react-router-dom'
5 |
6 | import client from '../apolloClient'
7 |
8 | import About from '../views/Home/about'
9 | import Index from '../views/Home/index'
10 | import Posts from '../views/Home/posts'
11 |
12 | class Home extends React.Component {
13 |
14 | render () {
15 | return (
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | )
24 | }
25 | }
26 |
27 | export default withApollo(withRouter(Home, {
28 | getUrl({ ctx }) {
29 | return ctx.url
30 | },
31 | basename: '/home'
32 | }), client)
33 |
--------------------------------------------------------------------------------
/packages/serlina-serve/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "serlina-serve",
3 | "version": "1.0.0",
4 | "description": "A simple Serlina web server",
5 | "scripts": {
6 | "test": "jest"
7 | },
8 | "bin": {
9 | "serlina-serve": "./bin/serlina-serve"
10 | },
11 | "dependencies": {
12 | "koa": "^2",
13 | "serlina": "^1",
14 | "glob": "^7.1.3",
15 | "serlina-koa": "^1",
16 | "yargs": "^12.0.1"
17 | },
18 | "devDependencies": {
19 | "supertest": "^3",
20 | "react": "^16",
21 | "react-dom": "^16"
22 | },
23 | "peerDependencies": {
24 | "react": "^16",
25 | "react-dom": "^16"
26 | },
27 | "repository": {
28 | "type": "git",
29 | "url": "git+https://github.com/djyde/serlina.git"
30 | },
31 | "keywords": [
32 | "react",
33 | "serverside-rendering"
34 | ],
35 | "bugs": {
36 | "url": "https://github.com/djyde/serlina/issues"
37 | },
38 | "homepage": "https://serlina.js.org",
39 | "author": "Randy",
40 | "license": "MIT"
41 | }
42 |
--------------------------------------------------------------------------------
/packages/serlina-apollo/src/withApollo.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import { ApolloProvider, getDataFromTree } from 'react-apollo'
3 |
4 | export default (WrappedComponent, client) => {
5 | return class SerlinaApolloProvider extends React.Component {
6 |
7 | static async getInitialProps(payload) {
8 | const c = client()
9 |
10 | let wrappedProps = {}
11 |
12 | if (WrappedComponent.getInitialProps) {
13 | wrappedProps = await WrappedComponent.getInitialProps(payload)
14 | }
15 |
16 | await getDataFromTree((
17 |
18 |
19 |
20 | ))
21 | const state = c.extract()
22 | return {
23 | initialData: state,
24 | wrappedProps
25 | }
26 | }
27 |
28 | render() {
29 | return (
30 |
31 |
32 |
33 | )
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Randy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | # Javascript Node CircleCI 2.0 configuration file
2 | #
3 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details
4 | #
5 | version: 2
6 | jobs:
7 | build:
8 | docker:
9 | # specify the version you desire here
10 | - image: circleci/node:8.9.0
11 |
12 | # Specify service dependencies here if necessary
13 | # CircleCI maintains a library of pre-built images
14 | # documented at https://circleci.com/docs/2.0/circleci-images/
15 | # - image: circleci/mongo:3.4.4
16 |
17 | working_directory: ~/repo
18 |
19 | steps:
20 | - checkout
21 |
22 | # Download and cache dependencies
23 | - restore_cache:
24 | keys:
25 | - v1-dependencies-{{ checksum "package.json" }}
26 | # fallback to using the latest cache if no exact match is found
27 | - v1-dependencies-
28 |
29 | - run: yarn install
30 |
31 | - run: npm run bootstrap -- --npmClient yarn
32 |
33 | - save_cache:
34 | paths:
35 | - node_modules
36 | key: v1-dependencies-{{ checksum "package.json" }}
37 |
38 | # run tests!
39 | - run: yarn test
40 |
41 |
--------------------------------------------------------------------------------
/docs/guide/getting-started.md:
--------------------------------------------------------------------------------
1 | ## Getting Started
2 |
3 | Let's start with a most simple example.
4 |
5 | Create a folder structure like:
6 |
7 | ```bash
8 | ├── index.js
9 | ├── pages
10 | │ └── page1.js
11 | ```
12 |
13 | And install serlina:
14 |
15 | ```
16 | npm i serlina react react-dom --save
17 | ```
18 |
19 | Firstly write your first page:
20 |
21 | ```js
22 | // pages/page1.js
23 |
24 | export default () => {
25 | return Hello Serlina!
26 | }
27 | ```
28 |
29 | And implement a most simple http server:
30 |
31 | ```js
32 | // index.js
33 |
34 | const { Serlina } = require('serlina')
35 | const path = require('path')
36 |
37 | const http = require('http')
38 |
39 | const serlina = new Serlina({
40 | baseDir: path.resolve(__dirname, './')
41 | })
42 |
43 | serlina.prepare()
44 | .then(() => {
45 | http.createServer(async (req, res) => {
46 | res.writeHead(200, { 'Content-Type': 'text/html' })
47 | if (req.url === '/page1') {
48 | const rendered = await serlina.render('page1')
49 | res.write(rendered.body)
50 | } else {
51 | res.write('works!')
52 | }
53 | res.end()
54 | }).listen(8090)
55 | })
56 | .catch(console.error)
57 | ```
58 |
59 | Open `http://localhost:8090/page1`, you will see the page you wrote in React!
--------------------------------------------------------------------------------
/packages/serlina-koa/README.md:
--------------------------------------------------------------------------------
1 | # serlina-koa
2 |
3 | [](https://npm.im/serlina-koa)
4 | [](https://npm.im/serlina-koa)
5 | [](https://circleci.com/gh/djyde/serlina)
6 |
7 | 🚨 [WIP]
8 |
9 | Serlina binding for Koa
10 |
11 | ## Usage
12 |
13 | ```
14 | npm react react-dom serlina-koa --save
15 | ```
16 |
17 | ```js
18 | // your-server.js
19 |
20 | const Koa = require('koa')
21 | const {Serlina} = require('serlina')
22 | const path = require('path')
23 |
24 | // init Serlina
25 | const serlina = new Serlina({
26 | baseDir: path.resolve(__dirname, './')
27 | })
28 |
29 | const serlinaKoa = require('../')
30 |
31 | const app = new Koa()
32 |
33 | serlina.prepare().then(() => {
34 |
35 | // map the url
36 | app.use(serlinaKoa({
37 | serlina,
38 | map: {
39 | '/page1': 'page1'
40 | }
41 | }))
42 |
43 | app.listen(3001, () => {
44 | console.log('Started on http://localhost:3001')
45 | })
46 |
47 | })
48 | ```
49 |
50 | ## API
51 |
52 | ### serlinaKoa(options)
53 |
54 | #### options
55 |
56 | - **serlina** Serlina instance
57 | - **map** a map object to map the url that should render Serlina page
58 |
59 | # License
60 |
61 | MIT License
62 |
--------------------------------------------------------------------------------
/packages/serlina-react-router/README.md:
--------------------------------------------------------------------------------
1 | # serlina-react-router
2 |
3 | [](https://npm.im/serlina-react-router)
4 | [](https://npm.im/serlina-react-router)
5 |
6 | ## Usage
7 |
8 | ```
9 | npm i react-router-dom serlina-react-router --save
10 | ```
11 |
12 | ```js
13 | class Home extends React.Component {
14 |
15 | render () {
16 | return (
17 |
18 |
Home
19 |
20 |
21 |
22 |
23 |
24 |
25 | )
26 | }
27 | }
28 |
29 | export default withRouter(Home, {
30 | getUrl({ ctx }) {
31 | return ctx.url
32 | }
33 | })
34 | ```
35 |
36 | ### options
37 |
38 | - `getUrl: (payload) => string` should return current url
39 | - [`basename`](https://reacttraining.com/react-router/web/api/BrowserRouter/basename-string) The base URL for all location.
40 |
41 | ### Use with [serlina-apollo](/packages/serlina-apollo/README.md)
42 |
43 | ```js
44 | export default withApollo(withRouter(Home, {
45 | getUrl({ ctx }) {
46 | return ctx.url
47 | }
48 | }), client)
49 | ```
50 |
51 | # License
52 |
53 | MIT License
--------------------------------------------------------------------------------
/examples/apollo/pages/home.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | import { ApolloClient } from 'apollo-client'
4 | import { Query } from 'react-apollo'
5 | import { InMemoryCache } from "apollo-cache-inmemory"
6 | import { createHttpLink } from 'apollo-link-http'
7 | import { withApollo } from 'serlina-apollo'
8 | import * as gql from 'graphql-tag'
9 | import * as fetch from 'isomorphic-fetch'
10 |
11 | const client = (initialState = {}) => {
12 | return new ApolloClient({
13 | ssrMode: true,
14 | cache: new InMemoryCache().restore(initialState),
15 | link: createHttpLink({
16 | uri: 'https://w5v4jr97kz.lp.gql.zone/graphql',
17 | fetch
18 | })
19 | })
20 | }
21 |
22 | export default withApollo(() => {
23 | return (
24 |
25 |
33 | {({ loading, data }) => {
34 | if (loading) {
35 | return "loading"
36 | } else {
37 | const posts = data.posts || []
38 | return (
39 |
40 | {posts.map(post => {
41 | return
{post.title}
42 | })}
43 |
44 | )
45 | }
46 | }}
47 |
48 |
49 | )
50 | }, client)
--------------------------------------------------------------------------------
/packages/serlina-react-router/src/withRouter.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import { BrowserRouter, StaticRouter } from 'react-router-dom'
3 |
4 | type options = {
5 | getUrl: (payload: any) => string,
6 | basename?: string
7 | }
8 |
9 | export default (WrappedComponent, options: options) => {
10 | return class WithRouter extends React.Component {
11 |
12 | static async getInitialProps (payload) {
13 |
14 | const url = options.getUrl(payload)
15 |
16 | let wrappedComponentProps = {}
17 |
18 | if (WrappedComponent.getInitialProps) {
19 | wrappedComponentProps = await WrappedComponent.getInitialProps(payload)
20 | }
21 |
22 | return {
23 | wrappedComponentProps,
24 | url,
25 | context: {}
26 | }
27 | }
28 |
29 | render () {
30 | // @ts-ignore
31 | if (process.browser) {
32 | return (
33 |
34 |
35 |
36 | )
37 | } else {
38 | return (
39 |
44 |
45 |
46 | )
47 | }
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Serlina - A progressive React Serverside Rendering framwork
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
28 |
29 |
30 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/packages/serlina-apollo/README.md:
--------------------------------------------------------------------------------
1 | # serlina-apollo
2 |
3 | [](https://npm.im/serlina-apollo)
4 | [](https://npm.im/serlina-apollo)
5 |
6 | Delightful using Apollo in Serlina.
7 |
8 | ## Usage
9 |
10 | ```
11 | npm i apollo-boost react-apollo serlina-apollo isomorphic-fetch --save
12 | ```
13 |
14 | Create an apollo client for serlina-apollo:
15 |
16 | ```js
17 | import { ApolloClient } from 'apollo-client'
18 | import { InMemoryCache } from "apollo-cache-inmemory"
19 | import { createHttpLink } from 'apollo-link-http'
20 | import * as fetch from 'isomorphic-fetch'
21 |
22 | const client = (initialState = {}) => {
23 | return new ApolloClient({
24 | ssrMode: true,
25 | cache: new InMemoryCache().restore(initialState),
26 | link: createHttpLink({
27 | uri: 'YOUR_URL',
28 | fetch
29 | })
30 | })
31 | }
32 | ```
33 |
34 | > `uri` must be an absolute URI. See [Apollo document for server-side rendering](https://www.apollographql.com/docs/react/features/server-side-rendering.html#server-initialization)
35 |
36 |
37 | Use `` in your page or anywhere:
38 |
39 | ```js
40 | import { Query } from 'react-apollo'
41 | import { withApollo } from 'serlina-apollo'
42 | import * as gql from 'graphql-tag'
43 |
44 | export default withApollo(() => {
45 | return (
46 |
47 |
55 | {({ loading, data }) => {
56 | if (loading) {
57 | return "loading"
58 | } else {
59 | const posts = data.posts || []
60 | return (
61 |
62 | {posts.map(post => {
63 | return
{post.title}
64 | })}
65 |
66 | )
67 | }
68 | }}
69 |
70 |
71 | )
72 | }, client)
73 | ```
74 |
75 | # License
76 |
77 | MIT License
--------------------------------------------------------------------------------
/packages/serlina/lib/components/Document.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import * as serialize from 'serialize-javascript'
3 | export interface DocumentProps {
4 | pageStyles: string[],
5 | pageScripts: string[],
6 | initialProps: any,
7 | publicPath: string,
8 | children?: React.ReactNode,
9 | helmet: any,
10 | inlineCSSString: null | string[],
11 | body: string,
12 | pageName: string,
13 | }
14 |
15 | export default ({
16 | pageStyles,
17 | pageScripts,
18 | initialProps = {},
19 | publicPath,
20 | body,
21 | pageName,
22 | inlineCSSString,
23 | helmet
24 | }: DocumentProps) => {
25 |
26 | const scripts = [...pageScripts]
27 |
28 | const main = scripts.pop()
29 | const vendors = scripts.pop()
30 | const otherScripts = scripts
31 |
32 | return (
33 |
34 |
35 | {helmet.title.toComponent()}
36 | {helmet.meta.toComponent()}
37 | {helmet.script.toComponent()}
38 | {helmet.noscript.toComponent()}
39 | {helmet.style.toComponent()}
40 | {helmet.link.toComponent()}
41 | {inlineCSSString ? inlineCSSString.map(str => {
42 | return
43 | }) : pageStyles.map(url => {
44 | return
45 | })}
46 |
53 |
54 |
55 |
56 | { }
57 | {otherScripts.map(script => {
58 | return
59 | })}
60 | { }
61 |
62 |
63 | )
64 | }
--------------------------------------------------------------------------------
/packages/serlina/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "serlina",
3 | "version": "2.0.7",
4 | "description": "A progressive React serverside-rendering framework",
5 | "main": "dist/index.js",
6 | "bin": {
7 | "serlina": "bin/serlina"
8 | },
9 | "files": [
10 | "dist",
11 | "head.js",
12 | "bin",
13 | "babel.config.js"
14 | ],
15 | "scripts": {
16 | "start": "tsc --watch",
17 | "build": "tsc",
18 | "doc": "docute ./docs",
19 | "clean": "rimraf dist",
20 | "demo": "node ./examples/sample",
21 | "test": "npm run build && jest",
22 | "prepublish": "npm run clean && npm run build"
23 | },
24 | "peerDependencies": {
25 | "react": "^16",
26 | "react-dom": "^16"
27 | },
28 | "dependencies": {
29 | "glob": "^7.1.3",
30 | "assets-webpack-plugin": "^3.8.4",
31 | "@babel/core": "^7.1.0",
32 | "@babel/preset-env": "^7.1.0",
33 | "@babel/polyfill": "^7.0.0",
34 | "@babel/preset-react": "^7",
35 | "babel-loader": "^8",
36 | "@babel/plugin-proposal-class-properties": "^7.1.0",
37 | "ts-loader": "^5.3.0",
38 | "css-loader": "^1.0.0",
39 | "mini-css-extract-plugin": "^0.4.1",
40 | "push-if": "^1.0.1",
41 | "react-helmet": "^5.2.0",
42 | "rimraf": "^2.6.2",
43 | "style-loader": "^0.21.0",
44 | "webpack": "^4.16.3",
45 | "webpack-dev-server": "^3.1.5",
46 | "webpack-merge": "^4.1.4",
47 | "webpack-serve": "^2.0.2",
48 | "webpackbar": "^2.6.1",
49 | "write-file-webpack-plugin": "^4.3.2",
50 | "serialize-javascript": "^1.5.0",
51 | "yargs": "^12.0.1",
52 | "webpack-node-externals": "^1.7.2"
53 | },
54 | "devDependencies": {
55 | "@types/node": "^10.5.5",
56 | "@types/react": "^16.4.7",
57 | "@types/react-dom": "^16.0.6",
58 | "docute": "^3.4.12",
59 | "jest": "^23.4.2",
60 | "react": "^16.4.2",
61 | "react-dom": "^16.4.2",
62 | "typescript": "^3.0.1"
63 | },
64 | "repository": {
65 | "type": "git",
66 | "url": "git+https://github.com/djyde/serlina.git"
67 | },
68 | "keywords": [
69 | "react",
70 | "serverside-rendering"
71 | ],
72 | "author": "Randy",
73 | "license": "MIT",
74 | "bugs": {
75 | "url": "https://github.com/djyde/serlina/issues"
76 | },
77 | "homepage": "https://serlina.js.org"
78 | }
79 |
--------------------------------------------------------------------------------
/packages/serlina/test/unit/__snapshots__/index.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Serlina dev mode nested page 1`] = `
4 | ""
8 | `;
9 |
10 | exports[`Serlina dev mode snapshot 1`] = `
11 | ""
15 | `;
16 |
17 | exports[`Serlina dev mode snapshot 2`] = `
18 | ""
22 | `;
23 |
24 | exports[`Serlina inline css inline css 1`] = `
25 | ""
32 | `;
33 |
--------------------------------------------------------------------------------
/docs/api.md:
--------------------------------------------------------------------------------
1 | # API
2 |
3 | ## new Serlina(options)
4 |
5 | return `serlina` instance.
6 |
7 | ### options
8 |
9 | > option is required when it is marked as ❗️
10 |
11 | #### baseDir
12 |
13 | `string`❗ An absolute path to your Serlina app.
14 |
15 | #### dev
16 |
17 | `boolean` dev mode.
18 |
19 | #### outputPath
20 |
21 | `string` the output path of Serlina built files. `path.resolve(baseDir, '.serlina')` is by default.
22 |
23 | #### publicPath
24 |
25 | `string` Webpack's publicPath. It works only when dev mode is `false`.
26 |
27 | #### host
28 |
29 | `string` Dev server host. `127.0.0.1` by default.
30 |
31 | #### port
32 |
33 | `number` Dev server port. `3000` by default.
34 |
35 | #### useStream
36 |
37 | `boolean` Use `renderToNodeStream()` instead of `renderToString()`. `false` by default.
38 |
39 | #### inlineCSS
40 |
41 | `boolean` Use inline `