Skip to content

Commit d8479dc

Browse files
committed
PDF working
1 parent a59e8c7 commit d8479dc

12 files changed

+4698
-0
lines changed

.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.DS_Store
2+
.merlin
3+
.bsb.lock
4+
npm-debug.log
5+
/lib/bs/
6+
/node_modules/
7+
*.bs.js

README.md

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# reason-react-lazy-loading
2+
3+
Example project to show how to use components lazy loading in ReasonReact.
4+
5+
## Run Project
6+
7+
```sh
8+
yarn install
9+
yarn start
10+
# in another tab
11+
yarn run webpack
12+
```
13+
14+
After you see the webpack compilation succeed (the `yarn run webpack` step), open up `build/index.html` (**no server needed!**). Then modify whichever `.re` file in `src` and refresh the page to see the changes.
15+
16+
**For more elaborate ReasonReact examples**, please see https://github.com/reasonml-community/reason-react-example
17+
18+
## Run Project with Server
19+
20+
To run with the webpack development server run `yarn run server` and view in the browser at http://localhost:8000. Running in this environment provides hot reloading and support for routing; just edit and save the file and the browser will automatically refresh.
21+
22+
Note that any hot reload on a route will fall back to the root (`/`), so `ReasonReact.Router.dangerouslyGetInitialUrl` will likely be needed alongside the `ReasonReact.Router.watchUrl` logic to handle routing correctly on hot reload refreshes or simply opening the app at a URL that is not the root.
23+
24+
To use a port other than 8000 set the `PORT` environment variable (`PORT=8080 yarn run server`).
25+
26+
## Build for Production
27+
28+
```sh
29+
yarn run clean
30+
yarn run build
31+
yarn run webpack:production
32+
```
33+
34+
This will replace the development artifact `build/Index.js` for an optimized version as well as copy `src/index.html` into `build/`. You can then deploy the contents of the `build` directory (`index.html` and `Index.js`).
35+
36+
If you make use of routing (via `ReasonReact.Router` or similar logic) ensure that server-side routing handles your routes or that 404's are directed back to `index.html` (which is how the dev server is set up).
37+
38+
**To enable dead code elimination**, change `bsconfig.json`'s `package-specs` `module` from `"commonjs"` to `"es6"`. Then re-run the above 2 commands. This will allow Webpack to remove unused code.

bsconfig.json

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
{
3+
"name": "react-hooks-template",
4+
"reason": {
5+
"react-jsx": 3
6+
},
7+
"sources": {
8+
"dir" : "src",
9+
"subdirs" : true
10+
},
11+
"package-specs": [{
12+
"module": "commonjs",
13+
"in-source": true
14+
}],
15+
"suffix": ".bs.js",
16+
"namespace": true,
17+
"bs-dependencies": [
18+
"reason-react"
19+
],
20+
"refmt": 3
21+
}

package.json

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "reason-react-lazy-loading",
3+
"version": "0.1.0",
4+
"scripts": {
5+
"build": "bsb -make-world",
6+
"start": "bsb -make-world -w",
7+
"clean": "bsb -clean-world",
8+
"test": "echo \"Error: no test specified\" && exit 1",
9+
"webpack": "webpack -w",
10+
"webpack:production": "NODE_ENV=production webpack",
11+
"server": "webpack-dev-server"
12+
},
13+
"keywords": [
14+
"BuckleScript"
15+
],
16+
"author": "",
17+
"license": "MIT",
18+
"dependencies": {
19+
"@react-pdf/renderer": "^1.5.5",
20+
"react": "^16.8.1",
21+
"react-dom": "^16.8.1",
22+
"reason-react": ">=0.7.0"
23+
},
24+
"devDependencies": {
25+
"bs-platform": "^5.0.3",
26+
"html-webpack-plugin": "^3.2.0",
27+
"webpack": "^4.0.1",
28+
"webpack-cli": "^3.1.1",
29+
"webpack-dev-server": "^3.1.8"
30+
}
31+
}

src/App.re

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
type action =
2+
| Clicked
3+
| InputChanged(string);
4+
5+
type state = {
6+
name: string,
7+
showPDFPreview: bool,
8+
};
9+
10+
let reducer = (state, action) =>
11+
switch (action) {
12+
| Clicked => {...state, showPDFPreview: true}
13+
| InputChanged(value) => {...state, name: value}
14+
};
15+
16+
[@react.component]
17+
let make = () => {
18+
let (state, dispatch) =
19+
React.useReducer(reducer, {name: "", showPDFPreview: false});
20+
21+
let greeting = "Hello " ++ state.name;
22+
23+
<div className="App">
24+
<input
25+
placeholder="Enter your name"
26+
type_="text"
27+
onChange={e =>
28+
dispatch(InputChanged(e->ReactEvent.Form.target##value))
29+
}
30+
/>
31+
<button onClick={_ => dispatch(Clicked)}>
32+
"Generate PDF"->React.string
33+
</button>
34+
{state.showPDFPreview ? <PdfPreview title=greeting /> : React.null}
35+
</div>;
36+
};

src/Bindings.re

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
module StyleSheet = {
2+
type t;
3+
[@bs.module "@react-pdf/renderer"] external make: t = "StyleSheet";
4+
[@bs.send] external create: (t, Js.t('a)) => Js.t('a) = "";
5+
};
6+
7+
module PDFViewer = {
8+
[@bs.module "@react-pdf/renderer"] [@react.component]
9+
external make:
10+
(~children: React.element, ~className: string, ~style: Js.t('a)) =>
11+
React.element =
12+
"PDFViewer";
13+
};
14+
15+
module Document = {
16+
[@bs.module "@react-pdf/renderer"] [@react.component]
17+
external make: (~children: React.element) => React.element = "Document";
18+
};
19+
20+
module Page = {
21+
[@bs.module "@react-pdf/renderer"] [@react.component]
22+
external make:
23+
(~children: React.element, ~size: string, ~style: Js.t('a)) =>
24+
React.element =
25+
"Page";
26+
};
27+
28+
module View = {
29+
[@bs.module "@react-pdf/renderer"] [@react.component]
30+
external make: (~children: React.element, ~style: Js.t('a)) => React.element =
31+
"View";
32+
};
33+
34+
module Text = {
35+
[@bs.module "@react-pdf/renderer"] [@react.component]
36+
external make:
37+
(~children: React.element, ~style: Js.t('a)=?) => React.element =
38+
"Text";
39+
};

src/Index.re

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ReactDOMRe.renderToElementWithId(<App />, "app");

src/PdfPreview.re

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
open Bindings;
2+
3+
// Create Document Component
4+
[@react.component]
5+
let make = (~title) =>
6+
<PDFViewer className="viewer" style=PdfStyles.styles##viewer>
7+
<Document>
8+
<Page size="A4" style={PdfStyles.styles##page}>
9+
<View style={PdfStyles.styles##section}>
10+
<Text style={PdfStyles.styles##title}> title->React.string </Text>
11+
<Text>
12+
"This is a text in a generated PDF file."->React.string
13+
</Text>
14+
</View>
15+
</Page>
16+
</Document>
17+
</PDFViewer>;

src/PdfStyles.re

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
let styles =
2+
Bindings.StyleSheet.(
3+
make->create({
4+
"viewer": {
5+
"padding": 0,
6+
},
7+
8+
"page": {
9+
"margin": 0,
10+
"flexDirection": "row",
11+
"backgroundColor": "#ffffff",
12+
},
13+
"title": {
14+
"fontSize": 30,
15+
"marginBottom": 30,
16+
},
17+
"section": {
18+
"margin": 10,
19+
"padding": 10,
20+
"flexGrow": 1,
21+
},
22+
})
23+
);

src/index.html

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>ReasonReact lazy and suspense</title>
6+
</head>
7+
<body>
8+
<div id="app"></div>
9+
<script src="Index.js"></script>
10+
</body>
11+
</html>

webpack.config.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const path = require('path');
2+
const HtmlWebpackPlugin = require('html-webpack-plugin');
3+
const outputDir = path.join(__dirname, 'build/');
4+
5+
const isProd = process.env.NODE_ENV === 'production';
6+
7+
module.exports = {
8+
entry: './src/Index.bs.js',
9+
mode: isProd ? 'production' : 'development',
10+
output: {
11+
path: outputDir,
12+
filename: 'Index.js'
13+
},
14+
plugins: [
15+
new HtmlWebpackPlugin({
16+
template: 'src/index.html',
17+
inject: false
18+
})
19+
],
20+
devServer: {
21+
compress: true,
22+
contentBase: outputDir,
23+
port: process.env.PORT || 8000,
24+
historyApiFallback: true
25+
}
26+
};

0 commit comments

Comments
 (0)