В Webpack 4, можем ли мы динамически генерировать порцию страницы с помощью токена import (), чтобы мы могли превратить реагирующий компонент в реактивно загружаемый? - PullRequest
0 голосов
/ 25 февраля 2019

Мы используем реаги и реагируемо загружаемы .

Во время инициализации нашего приложения мы проверяем, существует ли метод component.preload для каждого определяемого нами <Route />.

Если метод отсутствует, мы отображаем предупреждение о том, что компонент должен быть загружаемым.

Мы используем webpack 4, есть ли способ автоматически обернуть компонент, поэтому нам не нужносделать это вручную?

Вот как выглядит компонент:

/** MyComponent.js: page component */
export default () => <div>Hello world</div>;

Это тот же компонент, включенный в реактивно загружаемый компонент:

/**
 * preconfigured react-loadable 
 * See https://github.com/jamiebuilds/react-loadable#how-do-i-avoid-repetition)
 */
import MyLoadable from '@scopped/react-loadable';

/** loadable component */
export default MyLoadable({
  loader: () => import('./MyComponent'), /** import page component */
});
  1. Наши <Route /> объявлены в node_modules и из разных пакетов.
  2. Может быть объявлено с использованием <Resource /> (от act-admin ) вместо <Route />
  3. Они не распространяются в формате ESMно только CJS (CommonJS).

1 Ответ

0 голосов
/ 25 февраля 2019

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

Это немного странно, но должно работать (только с импортом, но вы можете настроить его так, как вам нужно):

Webpack config:

{
  test: /\.js$/,
  exclude: /node_modules/,
  use: {
    loader: [
      "babel-loader", // Rest of your loaders
      path.resolve(__dirname, 'path/to/your/loader.js')
    ]
  }
}

loader.js:

module.exports = function (source) {
  const routeRegex = new RegExp(/<Route.*component={(.*)}.*\/>/g);
  let matches;
  let components = [];

  while (matches = routeRegex.exec(source)) {
    components.push(matches[1]); // Get all the component import names
  }

  // Replace all import lines by a MyLoadable lines
  components.forEach((component) => {
    const importRegex = new RegExp(`import ${component} from '(.*)'`);
    const path = importRegex.exec(source)[1];

    source = source.replace(importRegex, `
      const ${component} = MyLoadable({
        loader: () => import('${path}')
      });
    `);
  });

  source = `
    import MyLoadable from './MyLoadable';
    ${source}
  `;

  return source;
};

Это определенно глупо, но если придерживаться соглашения, это может сработать.Он преобразует этот тип файла:

import Page1 from './Page1';
import Page2 from './Page2';

export default () => (
  <Switch>
    <Route path='/page1' component={Page1} />
    <Route path='/page2' component={Page2} />
  </Switch>
);

в этот файл:

import MyLoadable from './MyLoadable;

const Page1 = MyLoadable({
  loader: () => import('./Page1')
});

const Page2 = MyLoadable({
  loader: () => import('./Page2')
});

export default () => (
  <Switch>
    <Route path='/page1' component={Page1} />
    <Route path='/page2' component={Page2} />
  </Switch>
);

В этом примере есть некоторые проблемы (путь к MyLoadable должен быть абсолютным, он работает только тогда, когда Pageкомпоненты импортируются, загружаемые компоненты не находятся в отдельном файле, и это может привести к дублированию, ...) но вы поймете, что идея

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...