typescript-react-webpack4 起手与踩坑

前言

webpack4正式版发布也有一段时间了,为了从实际中感受变化,于是以typescript,react,结合之前翻译的一篇文章webpack-4.0更新日志(翻译),搭建一个可供项目使用的框架.

项目状况

github

前往

项目已使用

  • webpack-4
  • typescript
  • react
  • react-router-4
  • component hot reload
  • async component
  • import .(s)css auto generate .(s)css.d.ts
  • svg icon
  • Mobx
  • Antd

主要库及版本

  • webpack --------- 4.1.1
  • typescript --------- 2.9.2
  • react ------------ 16.3.2
  • react-router-dom -- 4.2.2
  • react-hot-loader --- 4.2.0
  • ......
  • node ------------- 8.11.2

原配置:

// tsconfig.json
{
  "compilerOptions": {
    "target": "es5","module": "es2015","moduleResolution": "node",....
  }
}
// webpack.config.js
{
    test: /\.(ts(x?)|js(x?))$/,exclude: /node_modules/,rules: [
      {
        loader: 'react-hot-loader/webpack',},{
        loader: 'ts-loader',options: {
          transpileOnly: true
        }
    }
}
Module not found: Error: Can't resolve 'react-hot-loader/webpack' in '/Users/jackple/Documents/react/ts-react-webpack4'

果然跑不通,符合心理预期!????

查看node_modules里面的react-hot-loader,对比原项目node_modules的react-hot-loader,文件结构改了不少,看4.0.0的源码,也不再有webpack目录,而且代码中有这么一段:

throw new Error('React Hot Loader: You are erroneously trying to use a Babel plugin ' + 'as a Webpack loader. We recommend that you use Babel,' + 'remove "react-hot-loader/babel" from the "loaders" section ' + 'of your Webpack configuration,and instead add ' + '"react-hot-loader/babel" to the "plugins" section of your .babelrc file. ' + 'If you prefer not to use Babel,replace "react-hot-loader/babel" with ' + '"react-hot-loader/webpack" in the "loaders" section of your Webpack configuration. ');

提示信息与实际不符,估计提示没改过来,还是用babel吧(其实它的README也是建议用babel),免得挣扎!

按照react-hot-loader官方推荐做法以及demo

When using TypeScript,Babel is not required,but React Hot Loader will not work without it. Just add babel-loader into your Webpack configuration,with React Hot Loader plugin.
{
  test: /\.tsx?$/,use: [
    {
      loader: 'babel-loader',options: {
        babelrc: true,plugins: ['react-hot-loader/babel'],'ts-loader',// (or awesome-typescript-loader)
  ],}
You also have to modify your tsconfig.json:
// tsconfig.json
{
  "module": "commonjs","target": "es6"
}
// xxx.tsx
import { hot } from 'react-hot-loader'
...
export default hot(module)(Component)
  1. 首先是react-hot-loader/babel,无论是按官方推荐配置,还是写在.babelrc,以上两者都加上环境判断,开发环境没问题,可是打包出来的生产环境代码看起来怪怪的:
...
default = i,u = r(4).
default,s = r(4).leaveModule,u && (u.register(l,"Error","/Users/jackple/Documents/react/ts-react-webpack4/src/components/Error/index.tsx"),u.register(i,"default",s(e))
}).call(this,r(12)(e))
...

怎么看都不合理呀! 为什么会出来我的本地源文件路径! 本地开nginx调试生产环境代码,虽然能跑,不过,这不是我想要的!

最后,这部分的处理结果是把react-hot-loader/babel删除之! 再将tsx接受hot reload还原为旧式写法:

import { AppContainer } from 'react-hot-loader'

import AppRouter from './router'

const render = Component => {
    ReactDOM.render(
        <AppContainer>
            <Component />
        </AppContainer>,document.getElementById('app') as HTMLElement
    )
}

render(AppRouter)

// Hot Module Replacement API
if (module.hot) {
    module.hot.accept(['router'],() => {
        import('./router').then(mod => render(mod.default))
    })
}
  1. 再者是为配合webpack4的代码分割(dynamic import),需要把tsconfig.json中的module置为esnext(主要是为了让typescript不编译import),不知道是不是我配置失误,显示以下错误:
ERROR in ./src/index.tsx
Module build failed: SyntaxError: 'import' and 'export' may only appear at the top level (14:8)

  12 | if (module.hot) {
  13 |     module.hot.accept(['router'],() => {
> 14 |         import('./router').then(mod => render(mod.default));
     |         ^
  15 |     });
  16 | }

不是说好的支持import语法了咩? 最后还是要加上syntax-dynamic-import的babel插件

bootstrap:74 Uncaught (in promise) TypeError: Cannot read property 'call' of undefined
    at i (bootstrap:74)
    at Object.31 (index.css:1)
    at i (bootstrap:74)
    at Object.32 (index.css?f62f:2)
    at i (bootstrap:74)
    at Object.52 (index.tsx:3)
    at i (bootstrap:74)
    at index.tsx:9
    at <anonymous>

过程曲折,还有一些问题没写上,具体请参考项目...

如果大家有更好的解决方案,也欢迎评论或提issue

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom