Skip to content

Commit 6fd85e8

Browse files
authored
Merge pull request #21 from fabyo82/feature/add_componentId
Implement SSR rendering support (#20) - add new options: - `ssr: boolean` to enable `componentId` based on file path and binding name - `displayName: boolean` to opt out display name generation - `styledIdentifiers: string[]` to allow custom wrappers - `rootCheck: string` to customize root recognition - known issues: - components with the same name and path get same component id - added example of SSR with express server
2 parents af3493d + 84df8b7 commit 6fd85e8

26 files changed

+4877
-70
lines changed

example/.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto

example/.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
dist/
2+
node_modules/
3+
4+
# OS generated files #
5+
######################
6+
.AppleDouble/
7+
.DS_Store
8+
.DS_Store?
9+
._*
10+
.Spotlight-V100
11+
.Trashes
12+
.idea
13+
*.happypack*
14+
ehthumbs.db
15+
Thumbs.db
16+
npm-debug.log

example/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# typescript-plugin-styled-components SSR example
2+
3+
## Getting Started
4+
5+
- Build `typescript-plugin-styled-components`
6+
7+
```
8+
$ cd ..
9+
```
10+
11+
```
12+
$ npm i
13+
```
14+
15+
```
16+
$ npm run build
17+
```
18+
19+
- Run example
20+
21+
```
22+
$ cd example
23+
```
24+
25+
```
26+
$ npm i
27+
```
28+
29+
```
30+
$ npm run dev
31+
```
32+
33+
Note: see [`ttypescript`](https://github.com/cevek/ttypescript) if you want to compile the server without webpack

example/package.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "ts-react-ssr-boilerplate",
3+
"version": "2.0.1",
4+
"description": "A starter boilerplate to create comprehensive React apps with TypeScript, Redux, Styled-Components and server-side rendering.",
5+
"author": "sandervispoel <contact@sandervispoel.com>",
6+
"repository": {
7+
"type": "git",
8+
"url": "https://github.com/sandervspl/ts-react-ssr-boilerplate"
9+
},
10+
"license": "MIT",
11+
"scripts": {
12+
"dev": "cross-env NODE_ENV=development webpack-cli --config webpack/config.server.js && node dist/server"
13+
},
14+
"dependencies": {
15+
"express": "^4.16.4",
16+
"react": "^16.6.0",
17+
"react-dom": "^16.6.0",
18+
"react-router": "^4.3.1",
19+
"react-router-dom": "^4.3.1",
20+
"styled-components": "^4.0.3"
21+
},
22+
"devDependencies": {
23+
"@types/express": "^4.16.0",
24+
"@types/react": "^16.4.18",
25+
"@types/react-dom": "^16.0.9",
26+
"@types/styled-components": "^4.0.3",
27+
"@types/webpack": "^4.4.17",
28+
"awesome-typescript-loader": "^5.2.1",
29+
"cross-env": "^5.2.0",
30+
"typescript": "^3.1.5",
31+
"webpack": "^4.23.1",
32+
"webpack-cli": "^3.1.2",
33+
"webpack-dev-middleware": "^3.4.0"
34+
}
35+
}

example/src/AppClient.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import * as React from 'react';
2+
import * as ReactDOM from 'react-dom';
3+
4+
import App from './app/App';
5+
import { ThemeProvider } from 'styled-components';
6+
import { BrowserRouter } from 'react-router-dom'
7+
8+
const app = document.getElementById('app');
9+
10+
ReactDOM.hydrate(
11+
12+
<ThemeProvider theme={{bgColor: 'red'}}>
13+
<BrowserRouter>
14+
<App />
15+
</BrowserRouter>
16+
</ThemeProvider>, app);
17+

example/src/app/App.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as React from 'react';
2+
import styled from 'styled-components';
3+
import { Component1 } from './Component1';
4+
5+
const BodyStyle = styled.div`
6+
background: blue;
7+
padding: 20px;
8+
`;
9+
10+
const Header = styled.h2`
11+
color: yellow;
12+
`;
13+
14+
class App extends React.Component<{}> {
15+
16+
render(){
17+
return (
18+
<div>
19+
<BodyStyle>
20+
<Header>Welcome to Typescript Styled Components SSR</Header>
21+
<Component1 />
22+
</BodyStyle>
23+
</div>
24+
);
25+
}
26+
}
27+
28+
export default App;

example/src/app/Component1.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import * as React from 'react';
2+
import styled from 'styled-components';
3+
4+
const Component1Style = styled.div`
5+
background: #fff;
6+
text-align: center;
7+
`;
8+
9+
const TextStyle = styled.h3`
10+
color: #000;
11+
font-weight: bold;
12+
`;
13+
export const Component1 : React.SFC = () => (
14+
<Component1Style>
15+
<TextStyle>SubComponent</TextStyle>
16+
</Component1Style>
17+
)

example/src/server/AppServer.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as React from 'React'
2+
import { ThemeProvider } from 'styled-components';
3+
import { StaticRouter } from 'react-router-dom'
4+
import App from '../app/App';
5+
export const AppServer = (url) => (
6+
<StaticRouter
7+
location={url}
8+
context={{}}
9+
>
10+
<ThemeProvider theme={{ bgColor: 'red' }}>
11+
<html>
12+
<head>
13+
<title>Test App</title>
14+
</head>
15+
<body>
16+
<div id="app"><App /></div>
17+
<script src="./app.js"></script>
18+
</body>
19+
</html>
20+
</ThemeProvider>
21+
</StaticRouter>)

example/src/server/index.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import * as React from 'react';
2+
import * as express from 'express';
3+
export const port = process.env.PORT || 3000;
4+
import { ServerStyleSheet } from 'styled-components';
5+
import { renderToNodeStream } from 'react-dom/server';
6+
import * as webpack from 'webpack';
7+
const webpackDevMiddleware = require('webpack-dev-middleware');
8+
import config from '../../webpack/config';
9+
import {AppServer} from './AppServer';
10+
11+
12+
const app = express();
13+
14+
const compiler = webpack(config);
15+
16+
app.use(webpackDevMiddleware(compiler, {
17+
publicPath: config.output.publicPath,
18+
historyApiFallback: true,
19+
hot: true,
20+
noInfo: true,
21+
stats: { colors: true },
22+
}));
23+
24+
app.get('/', (req, res) => {
25+
res.contentType('text/html');
26+
res.write('<!DOCTYPE html>');
27+
const sheet = new ServerStyleSheet();
28+
const jsx = sheet.collectStyles(<AppServer url={req.url}/>)
29+
const stream = sheet.interleaveWithNodeStream(renderToNodeStream(jsx))
30+
stream.pipe(
31+
res,
32+
{ end: false }
33+
)
34+
35+
});
36+
37+
38+
39+
app.listen(port, () => {
40+
console.log(`[${process.env.NODE_ENV}] server running on http://localhost:${port}/`);
41+
});

example/transformer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
const transformer = '../'

0 commit comments

Comments
 (0)