Разделение кода Webpack на приложение, использующее реле

Образец репозитория github (конкретная фиксация)

Я погружаюсь в реакцию / реле и хочу убедиться, что я настроен на запуск разработки и производства. У нас большое приложение, поэтому разделение кода является обязательным.

Я предпочитаю объявления маршрутов react-router на основе JSX, поэтому с радостью наткнулся на Неявное разделение кода и загрузка фрагментов с помощью React Router и Webpack из Эван Хенли.

С помощью нескольких настроек регулярного выражения и ES6 я смог заставить его метод работать. Клонируйте репозиторий, npm install && npm start и вы сможете перейти к разные чанки (за исключением задач).

^^^ все это работает для не ретрансляционных частей приложения - хорошая вещь.

Проблема

Затем ... перейдите в Todos (на основе реле).

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

Наше производственное приложение полностью зависит от реле.

Relay зависит от нескольких статических вызовов таких классов, как getFragment. В этом случае webpack поместил TodoListFooter в другой разделяемый блок, поэтому TodoListFooter2 не имеет getFragment. Напротив, в той же строке он прерывается, _AddTodoMutation2 находится в том же фрагменте, поэтому аналогичный вызов _AddTodoMutation2.default.getFragment('viewer') работает нормально.

Возможные решения

  1. Использовать именованные блоки? Этот коммит попытался сделать это, но все равно вставил некоторый код в общий кусок (и не удалось с той же ошибкой)
  2. Другой метод разделения кода, совместимый с реле для статических методов?
  3. Что-то, о чем я не подумал?

person kross    schedule 31.05.2016    source источник


Ответы (1)


Я смог понять, что, хотя подход Эвана Хенли был лучше, мне нужно было немного изменить его, чтобы сделать его совместимым с Relay (с ES6 + import).

Это требовало явного bundle?lazy в импорте ES6 для совместимости с реле. Этот коммит показывает основные различия, которые я обнаружил, чтобы сделать его ретранслятором совместимый.

В первую очередь, в коде Хенли требовалась конфигурация загрузчика веб-пакетов и импорт, например:

import Landing from './components/Landing'

Напротив, мой подход не требует дополнительной конфигурации загрузчика веб-пакетов с явной ленивой загрузкой пакетного загрузчика в import:

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

Метод Хенли делает импорт файла маршрута более чистым. Мой подход заставляет его работать с 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>
)
person kross    schedule 01.06.2016
comment
Вы подходите к работе с такими вещами, как Component.getFragment('viewer')? - person Konstantin Tarkus; 15.06.2016
comment
Это работает, образец репо работает и имеет пример реле todos (без стиля) - person kross; 15.06.2016