Skip to content
This repository has been archived by the owner on Jan 26, 2019. It is now read-only.

Enabling 'react-hot' on typescript project #3

Closed
Aranir opened this issue Dec 27, 2016 · 17 comments
Closed

Enabling 'react-hot' on typescript project #3

Aranir opened this issue Dec 27, 2016 · 17 comments
Labels

Comments

@Aranir
Copy link

Aranir commented Dec 27, 2016

Thank you for the template, it is very helpful.

There is just one thing I can't figure out yet, how can I simply add the 'hot-reloading' to the project?

I ejected it, added the react-hot-loader package with yarn and modified the loaders:

        {
            test: /\.(ts|tsx)$/,
            loaders: ['react-hot', 'ts'],
            include: paths.appSrc

        },

But it seems still to reload the whole page if I change a component.

Any help would be appreciated.

@wmonk wmonk added the question label Dec 28, 2016
@wmonk
Copy link
Owner

wmonk commented Dec 28, 2016

I have had react-hot-loader@3 working with standard ES6, but haven't tried with TS. I know there is definitely more configuration than just adding the loader like you have done which looks to be best described here - however, i'm not sure how this will work with typescript as it relies on a babel plugin.

@Aranir
Copy link
Author

Aranir commented Dec 28, 2016

I tried with react-hot-loader@3 (current beta version), but in typescript I don't find module.hot.

if (module.hot) {
  module.hot.accept('./containers/Root', () => {
    render(
      <AppContainer
        component={require('./containers/Root').default}
        props={{ store }}
      />,
      document.getElementById('root')
    );
  });
}

Any idea where i can get the definition for module.hot?

@wmonk
Copy link
Owner

wmonk commented Dec 28, 2016

This typing looks like it includes the neccessary definitions to enable module.hot

@wmonk
Copy link
Owner

wmonk commented Dec 28, 2016

I just had a quick play, and made the changes to get hot-reloading working, you can see the repo and commit here.

You will need to replace @types/node with @types/webpack-env as above. And install the other deps required by react-hot-loader@3.

I'm going to close this issue, as I think the above should be enough to get this working for you. But, want to keep react-scripts-ts as close to react-scripts as possible, so hot-reloading won't be adopted until it it's in the original repo.

@wmonk wmonk closed this as completed Dec 28, 2016
@Aranir
Copy link
Author

Aranir commented Dec 30, 2016

It nearly works. As long as I don't need to use the @types/node definition files in the project.

Unfortunately many libraries (written in typescript) require @types/node to be installed which then clashes with webpack-env as for example require is redefined.

I guess there is currently no fix for this...

@wmonk
Copy link
Owner

wmonk commented Jan 4, 2017

@Aranir just got back to work, and found the way it was handled here, hope this helps:

export interface WebpackNodeModule extends NodeModule {
  hot: {
    accept: (name: string, handler: () => void) => void
  };
}
import { WebpackNodeModule } from './typePatches/webpackNodeModule';

if ((module as WebpackNodeModule).hot) {
  // do stuff
}

it's not ideal, and is quite hacky, but would allow you to carry on using the @types/node definitions with HMR.

@cescoferraro
Copy link

@wmonk @Aranir
If its a webpack build, module is there. Just shush typescript and you are good to go.

declare const module:any

@subev
Copy link

subev commented Nov 29, 2017

yarn add "@types/webpack-env" and you should be all set

@kerwynrg
Copy link

kerwynrg commented Apr 3, 2018

I followed @gaearon recomendations in
https://github.com/gaearon/react-hot-loader#add-babel-after-typescript

and code from
https://github.com/strothj/react-app-rewire-typescript-babel-preset/blob/master/packages/rewire/rewireWebpack.ts

And I succeed with https://github.com/wmonk/create-react-app-typescript hot loader

This is what I did, hope it helps.

https://gist.github.com/kerwynrg/0ecf4d53345585e77b3fa694bad60d4d

@SeanRoberts
Copy link

@kerwynrg Thanks for sharing this. I still can't get it working though, my app just reloads and I don't get anything in the console from HMR. Would you mind sharing what your root/index component looks like? Did you have to add a .babelrc or anything else not covered in the gist? Thanks again for sharing, would really like to get this working!

@kerwynrg
Copy link

kerwynrg commented May 16, 2018

@SeanRoberts I updated the gist with mi Root and configureStore for dev environment, It includes some redux-saga code but if you don't use it, you can omit it.

Sometimes it inject code on demand, some other times app reloads to load, I don't remember what are the scenarios when this happens.

@SeanRoberts
Copy link

Thanks @kerwynrg, this looks a lot like what I have so I think something else in my stack (possibly another rewire package) might be causing the issue.

@kerwynrg
Copy link

@SeanRoberts What package are you using?

@SeanRoberts
Copy link

@kerwynrg I'm using the following:

react-app-rewire-styled-components
react-app-rewire-graphql-tag
react-app-rewire-svg-react-loader
react-app-rewire-hot-loader

I've also got the following in tsconfig:

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "outDir": "build/dist",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom", "esnext.asynciterable"],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "baseUrl": "./src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true
  },
  "exclude": [
    "node_modules",
    "build",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts"
  ]
}

Did you manually add babel-loader? Or anything in a babelrc file?

Really appreciate the help with this, it'd be great to get a definitive recipe together for getting hot reloading with react-scripts-ts!

@kerwynrg
Copy link

kerwynrg commented May 16, 2018

I don't have a .babelrc.

This is my tsconfig.json

{
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "build/dist",
    "module": "commonjs",
    "target": "es6",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "noUnusedLocals": true
  },
  "files": ["src/index.tsx"],
  "exclude": [
    "node_modules",
    "build",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts",
    "stories",
    ".storybook",
    "*.stories.tsx",
    "*.test.tsx"
  ],
  "types": ["typePatches"]
}

@SeanRoberts I see module and target are different.
@gaearon Mention target should be es6, maybe that's the issue

@SeanRoberts
Copy link

SeanRoberts commented May 16, 2018

@kerwynrg Unfortunately that's not it either. When I've got some time I'm going to try with a fresh app and then slowly add things back in until I find the problem. I'll update this ticket when I find a solution (as long as it's ok with @wmonk for us to keep using this issue tracker)

@ackvf
Copy link

ackvf commented Jul 16, 2018

Finally, I also made it work. pfeeew 😤

This is everything I did during the process, some of it might be unnecessary.
(The following is basically the diff with my last commit before enabling HMR.)

package.json
{
  "dependencies": {
    "react-app-rewire-hot-loader": "^1.0.1",
    "react-app-rewire-typescript": "^2.0.2",
    "react-app-rewired": "^1.5.2",
    "react-hot-loader": "^4.3.3",
    "react-scripts": "^1.1.4",
    "react-scripts-ts": "^2.16.0",
  },
  "scripts": {
    "start": "react-app-rewired start --scripts-version react-scripts-ts",
    "build": "react-app-rewired build --scripts-version react-scripts-ts",
    "test": "react-app-rewired test --env=jsdom --scripts-version react-scripts-ts",
    "eject": "react-app-rewired eject --scripts-version react-scripts-ts",
  },
  "devDependencies": {
    "@types/node": "^9.6.23",
    "@types/webpack-env": "^1.13.6",
  }
}
tsconfig.json
{
  "compilerOptions": {
    "target": "es6", // es6 required for babel-loader that is required for react-hot-loader : https://github.com/gaearon/react-hot-loader#add-babel-after-typescript
    "module": "esnext",
    "moduleResolution": "node"
  }
}
tsconfig.prod.json
{
  "extends": "./tsconfig",
  "target": "es5"
}
src\index.tsx (practically default)
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import registerServiceWorker from './registerServiceWorker'
import './index.css'

ReactDOM.render(
  <App/>,
  document.getElementById('root') as HTMLElement
)

registerServiceWorker()
src\App.tsx
//...
import { hot } from 'react-hot-loader'

class App extends React.Component {
  // ...
}

export default hot(module)(App)
config-overrides.js
const rewireTypescript = require('react-app-rewire-typescript')
const rewireReactHotLoader = require('react-app-rewire-hot-loader')

module.exports = function override(config, env) {
  config = rewireTypescript(config, env)
  config = rewireReactHotLoader(config, env)
  return config
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

7 participants