【问题标题】:Webpack code-splitting an app that uses relayWebpack 代码拆分使用中继的应用程序
【发布时间】:2016-09-30 03:21:14
【问题描述】:

Sample github repo(具体提交)

我正在深入研究反应/中继,并希望确保我已准备好开始开发与生产。我们有一个大型应用程序,因此必须进行代码拆分。

我更喜欢基于 JSX 的 react-router 路由声明,所以我很高兴从 Evan Henley 遇到 Implicit Code Splitting and Chunk Loading with React Router and Webpack。

通过对正则表达式和 ES6 的一些调整,我能够让他的方法正常工作。克隆the repo、npm install && npm start,您将能够导航到不同的块(待办事项除外)。

^^^所有这些都适用于应用程序的非中继部分 - 好东西。

问题

然后...导航到 Todos(基于中继)。

Uncaught TypeError: _TodoListFooter2.default.getFragment is not a function
viewer 
Fragment 
(instrumented buildRQL.Fragment) 
buildContainerFragment 

我们的生产应用将完全依赖于中继。

中继依赖于一些对类的静态调用,例如getFragment。在这种情况下,webpack 已经将TodoListFooter 推送到一个不同 共享块中,所以TodoListFooter2 没有getFragment。相比之下,在它中断的同一行上,_AddTodoMutation2 在同一个块中,因此类似的调用 _AddTodoMutation2.default.getFragment('viewer') 可以正常工作。

可能的解决方案

  1. 使用命名块? This commit 试图这样做,但它仍然将一些代码推送到共享块中(并因同样的错误而失败)
  2. 与静态方法兼容的不同代码拆分方法?
  3. 有什么我没想到的?

【问题讨论】:

    标签: webpack react-router relay


    【解决方案1】:

    我发现虽然 Evan Henley 的方法更好,但我需要稍微改变它以使其与 Relay 兼容(与 ES6+ import)。

    这需要在 ES6 导入中显式 bundle?lazy 才能与中继兼容。 This commit 显示了我发现的使其中继兼容的主要区别。

    首先,在 Henley 的代码中,它需要配置 webpack 加载器和导入,例如:

    import Landing from './components/Landing'
    

    相比之下,我的方法不需要额外的 webpack 加载器配置,并在 import 中使用显式的 bundle-loader 延迟加载:

    import Landing from 'bundle?lazy!./components/Landing'
    

    Henley 的方法使路由文件导入更清晰。我的方法使它可以与 Relay 一起使用,并且通过import 进行更明确的代码拆分,而无需通过正则表达式进行任何额外的webpack.config.js 加载程序配置。

    每个都很好,虽然我的方法是我发现使其中继兼容的唯一方法。

    实施:

    type GetComponent = (location?: string, cb: GetComponentCB) => void
    
    /**
     * Purpose: abbreviated expression so that we can read routes
     *
     * Background:
     *  - (failed) luqin/react-router-loader is awesome, but it is a Proxy and doesn't work with relay components.
     *    @see https://github.com/relay-tools/react-router-relay/issues/161
     *
     *  - (failed) webpack dynamic requires need a hard path root (the rest can be an expression)
     *    at compile time and a regex is created
     *    @see https://webpack.github.io/docs/html#dynamic-requires
     *    @see http://stackoverflow.com/a/37228426/2363935
     *
     *  - (succeeded ultimately) huge-app-splitting-refactor
     *    - uses bundle-loader, works with imports! and no path hardcoding!
     *    - approach doesn't work with Relay (quite as-is)
     *    - fixed approach with explicit bundle lazy imports!
     *    @see http://stackoverflow.com/a/37575707/2363935
     *    @see http://henleyedition.com/implicit-code-splitting-with-react-router-and-webpack/
     *    @see https://github.com/echenley/react-router-huge-apps-refactor
     *
     * @param component
     * @returns {function()}
     */
    export function lazy (lazyModule: Function): GetComponent {
      if (!lazyModule) {
        throw new Error('lazy() did not find the given module.  Check to be sure your import path is correct, and make sure you are pointing at a file with a ****default export****.')
      }
      return (location, cb) => {
        lazyModule((module) => {
          cb(null, module.default)
        })
      }
    }
    

    用法:

    /* eslint-disable flowtype/require-valid-file-annotation */
    import OrganizationQueries from '../../queries/OrganizationQueries'
    import React from 'react'
    import {Route} from 'react-router'
    import {lazy} from '../../config/routes'
    import Organization from 'bundle-loader?lazy!./Organization'
    
    // protected by parent route
    export default (
      <Route>
        <Route path='/organization' getComponent={lazy(Organization)} queries={OrganizationQueries} />
      </Route>
    )
    

    【讨论】:

    • 您是否使用Component.getFragment('viewer') 之类的东西来工作?
    • 确实如此,示例 repo 有效并且有 todos 中继示例(无样式)
    猜你喜欢
    • 2018-04-28
    • 2020-09-26
    • 2019-01-22
    • 2017-02-05
    • 1970-01-01
    • 2017-05-31
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多