├── .gitignore ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.md ├── docker-compose.yml ├── package.json ├── src ├── App.tsx ├── index.ejs └── index.tsx ├── tsconfig.json └── webpack.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # Project 2 | dist/ 3 | 4 | ### https://raw.github.com/github/gitignore/77e29837cf03b59fc4d885ea011bbd683caaaf85/node.gitignore 5 | 6 | # Logs 7 | logs 8 | *.log 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | 15 | # Directory for instrumented libs generated by jscoverage/JSCover 16 | lib-cov 17 | 18 | # Coverage directory used by tools like istanbul 19 | coverage 20 | 21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 22 | .grunt 23 | 24 | # node-waf configuration 25 | .lock-wscript 26 | 27 | # Compiled binary addons (http://nodejs.org/api/addons.html) 28 | build/Release 29 | 30 | # Dependency directory 31 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 32 | node_modules 33 | 34 | 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | - "6" 5 | script: 6 | - npm run build 7 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:7-alpine 2 | MAINTAINER Glavin Wiechert 3 | 4 | # Defines our working directory in container 5 | WORKDIR /usr/src/app 6 | 7 | COPY package.json ./ 8 | RUN npm install 9 | 10 | COPY . ./ 11 | RUN npm run build 12 | 13 | CMD npm run static -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Glavin Wiechert 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-hot-ts 2 | 3 | > Demo of React Hot Reloading + TypeScript 4 | 5 | ## Install prerequisites 6 | 7 | ``` 8 | npm install 9 | ``` 10 | 11 | ## Usage 12 | 13 | ``` 14 | npm start 15 | ``` 16 | 17 | ### Docker 18 | 19 | ``` 20 | docker-compose up --build 21 | ``` 22 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | 5 | react-hot-ts: 6 | container_name: react-hot-ts 7 | build: . 8 | ports: 9 | - "8080:8080" 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-hot-ts", 3 | "version": "0.1.0", 4 | "description": "Demo of React Hot Reloading + TypeScript", 5 | "main": "./dist/bundle.js", 6 | "dependencies": { 7 | "expose-loader": "^0.7.3", 8 | "html-webpack-plugin": "^2.28.0", 9 | "node-static": "^0.7.9", 10 | "react": "^15.5.4", 11 | "react-dom": "^15.5.4" 12 | }, 13 | "devDependencies": { 14 | "@types/html-webpack-plugin": "^2.28.0", 15 | "@types/node": "^8.0.9", 16 | "@types/react": "^15.0.24", 17 | "@types/react-dom": "^15.5.0", 18 | "@types/react-hot-loader": "^3.0.3", 19 | "@types/webpack": "^3.0.2", 20 | "@types/webpack-env": "^1.13.0", 21 | "awesome-typescript-loader": "^3.1.3", 22 | "react-hot-loader": "^3.0.0-beta.7", 23 | "source-map-loader": "^0.2.1", 24 | "ts-node": "^3.2.0", 25 | "typescript": "^2.3.3", 26 | "webpack": "^2.6.0", 27 | "webpack-dev-server": "^2.4.5" 28 | }, 29 | "scripts": { 30 | "build": "webpack", 31 | "start": "webpack-dev-server", 32 | "static": "static -at 0.0.0.0 dist", 33 | "test": "echo \"Error: no test specified\" && exit 1" 34 | }, 35 | "repository": { 36 | "type": "git", 37 | "url": "git+https://github.com/Glavin001/react-hot-ts.git" 38 | }, 39 | "author": "Glavin Wiechert", 40 | "license": "MIT", 41 | "bugs": { 42 | "url": "https://github.com/Glavin001/react-hot-ts/issues" 43 | }, 44 | "homepage": "https://github.com/Glavin001/react-hot-ts#readme" 45 | } 46 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | export default class App extends React.Component<{}, { count: number; }> { 4 | interval: number; 5 | state = { count: 0 }; 6 | 7 | //This state will be maintained during hot reloads 8 | componentWillMount() { 9 | this.interval = window.setInterval(() => { 10 | this.setState({ count: this.state.count + 1 }) 11 | }, 1000); 12 | } 13 | 14 | componentWillUnmount() { 15 | window.clearInterval(this.interval); 16 | } 17 | 18 | render() { 19 | return ( 20 |
21 |

Hello world!

22 |
Welcome to hot-reloading React written in TypeScript! {this.state.count}
23 |
24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom"; 3 | import { AppContainer } from "react-hot-loader"; 4 | import App from "./App"; 5 | 6 | const rootEl = document.getElementById("root"); 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | rootEl 12 | ); 13 | 14 | // Hot Module Replacement API 15 | if (module.hot) { 16 | module.hot.accept("./App", () => { 17 | const NextApp = require<{default: typeof App}>("./App").default; 18 | ReactDOM.render( 19 | 20 | 21 | 22 | , 23 | rootEl 24 | ); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/", 4 | "sourceMap": true, 5 | "noImplicitAny": true, 6 | "module": "commonjs", 7 | "target": "es5", 8 | "jsx": "react", 9 | "types": [ 10 | "webpack-env", 11 | "node" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /webpack.config.ts: -------------------------------------------------------------------------------- 1 | import * as webpack from "webpack"; 2 | import * as path from "path"; 3 | import * as HtmlWebpackPlugin from 'html-webpack-plugin'; 4 | 5 | const config: webpack.Configuration = { 6 | entry: [ 7 | "react-hot-loader/patch", 8 | "./src/index.tsx", 9 | ], 10 | output: { 11 | path: path.join(__dirname, 'dist'), 12 | filename: "bundle.js", 13 | }, 14 | 15 | // Enable sourcemaps for debugging webpack's output. 16 | devtool: "source-map", 17 | 18 | resolve: { 19 | // Add '.ts' and '.tsx' as resolvable extensions. 20 | extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"] 21 | }, 22 | 23 | plugins: [ 24 | new webpack.NamedModulesPlugin(), 25 | new webpack.HotModuleReplacementPlugin(), 26 | new HtmlWebpackPlugin({ 27 | title: 'react-hot-ts', 28 | chunksSortMode: 'dependency', 29 | template: path.resolve(__dirname, './src/index.ejs') 30 | }), 31 | ], 32 | 33 | module: { 34 | loaders: [ 35 | // All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'. 36 | { 37 | test: /\.tsx?$/, 38 | loaders: [ 39 | "react-hot-loader/webpack", 40 | "awesome-typescript-loader" 41 | ], 42 | exclude: path.resolve(__dirname, 'node_modules'), 43 | include: path.resolve(__dirname, "src"), 44 | }, 45 | // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'. 46 | { 47 | enforce: "pre", 48 | test: /\.js$/, 49 | loader: "source-map-loader" 50 | }, 51 | ] 52 | }, 53 | 54 | devServer: { 55 | hot: true 56 | } 57 | 58 | }; 59 | 60 | export default config; 61 | --------------------------------------------------------------------------------