Как изменить навигацию по дереву (пакет, который реэкспортирует модули) при загрузке с помощью приложения babel-preset-реагировать-приложение? - PullRequest
0 голосов
/ 11 июля 2019

Цели

Я пытаюсь интегрировать react-navigation в проект react-native-web, запущенный из шаблона Create React App TypeScript. Я хочу добиться наименьшего возможного размера пакета для моего веб-приложения React Native, но хочу также сохранить типизацию TypeScript.

Проблема

Я обнаружил, что когда я импортирую любой модуль из react-navigation (чья точка входа реэкспортирует многие другие модули), Webpack связывает каждый этих реэкспортированных модулей, даже если я не используя их. Это удваивает весь размер моего пакета!

Я не уверен, связано ли это с плохой архитектурой react-navigation (например, она не указывает "sideEffects": false в своем package.json), или из-за того, что Babel переносит импорт ES6 вниз в формат, который может не трясется Это все вне моей компетенции.

Моя настройка

Я дополнил стандартную конфигурацию Create React App с помощью rescripts (аналогично customise-cra). react-navigation было интегрировано следующим образом:

  1. Завершить навигацию React Начало работы Guide;
  2. Добавьте react-navigation и его различные зависимости в список CRA Babel, включая rescripts, как показано ниже.
// .rescriptsrc.js
const {getPaths, edit, getWebpackPlugin, paths} = require('@rescripts/utilities')

module.exports = config => {
    const isEnvDevelopment = config.mode === "development";

    /* Find the Babel loder. */
    const babelLoaderPaths = getPaths(
        x => {
            if(x && x.loader && x.loader.includes('babel-loader')){
                /* This distinguishes CRA's two babel-loaders.
                 * Here we select the application src loader. */
                return inQuestion.include === paths.src;
            }
            return false;
        },
        config
    );

    /* In customise-cra, this would be babelinclude() */
    config = edit(
        (babelLoader) => {
            babelLoader.include = [
                path.resolve("src"), // CRA holds just this line by default.

                /* These need transpiling (e.g. they contain JSX) */
                path.resolve("node_modules/@react-navigation"),
                path.resolve("node_modules/react-navigation"),
                path.resolve("node_modules/react-native-gesture-handler"),
                path.resolve("node_modules/react-native-screens"),
                path.resolve("node_modules/react-navigation-drawer"),
                path.resolve("node_modules/react-navigation-tabs"),
                path.resolve("node_modules/react-native-tab-view"),
            ];

            return babelLoader;
        },
        babelLoaderPaths,
        config
    );

    /* Emulate the Metro bundler's behaviour of injecting __DEV__ globally */
    const definePlugin = getWebpackPlugin("DefinePlugin", config);
    Object.assign(definePlugin.definitions, { __DEV__: `${isEnvDevelopment}` });
}

Размер пакета в зависимости от стратегии импорта

Для справки, мой базовый размер пакета (без react-navigation):

  • 91 765 строк кода, 721 КБ в комплекте разработчика
  • Минимизированный (производственный) комплект 361 КБ

Я не буду ссылаться на размеры gzip.

Импорт из react-navigation ???

react-navigation реэкспорт все из @react-navigation/core, @react-navigation/native и ряд других модулей, таких как react-navigation-drawer.

Все эти модули расточительно входят в мой комплект!

import { createAppContainer, createSwitchNavigator } from "react-navigation";

const appNavigator = createSwitchNavigator(/* Whatever */);
createAppContainer(appNavigator);

/*
- Adds 19,391 lines and 115 KB to dev bundle
- Adds 352 KB to minified (production) bundle
*/

Импорт из субмодулей @react-navigation 10

  • @react-navigation/core реэкспортирует различные модули, такие как TabRouter, которые я не буду использовать.
  • @react-navigation/native реэкспортирует различные модули, такие как FlatList, которые я не буду использовать.

Все эти модули бесполезно входят в мой комплект, но, по крайней мере, он не связывает модули, подобные react-navigation-drawer!

? Проблема: мы теряем набор текста!

const RNCore: any = require("@react-navigation/core");
const RNNative: any = require("@react-navigation/native");

const appNavigator = RNNative.createSwitchNavigator(/* Whatever */);
RNCore.createAppContainer(appNavigator);

/*
- Adds 9,004 lines and 55 KB to dev bundle
- Adds 226 KB to minified (production) bundle
*/

Импорт напрямую из целевого модуля ?

Эти модули ничего не реэкспортируют, и импорт таким образом приводит к наименьшему размеру пакета.

К сожалению, createAppContainer сам импортирует некоторые модули из @react-navigation/core, и я вижу, что пакет, таким образом, тратит впустую все, что также реэкспортируется из @react-navigation/core, поэтому он все еще не идеален.

? Проблема: мы теряем набор текста!

const createSwitchNavigator: any = require("@react-navigation/core/lib/commonjs/navigators/createSwitchNavigator").default;
const createAppContainer: any = require("@react-navigation/native/dist/createAppContainer").default;

const appNavigator = createSwitchNavigator(/* Whatever */);
createAppContainer(appNavigator);

/*
- Adds 7,000 lines and 40 KB to dev bundle
- Adds 75 KB to minified bundle
*/

Дальнейшее чтение

Эта проблема является сценарием использования для babel-transform-imports, babel-plugin-import и babel-plugin-direct-import. Однако это были очень хитрые обходные пути, представленные два года назад. Я надеюсь, что сейчас есть лучшее современное состояние.

...