Условно импортировать активы в приложение create-реагировать

Можно ли условно импортировать активы при создании приложения React с помощью create-реагировать на приложение? Я знаю о синтаксисе require - пример:

import React from "react";


const path = process.env.REACT_APP_TYPE === "app_1" ? "app_1" : "app_2";

const imagePath = require('./assets/${path}/main.png');

export default function Test() {
  return (
      <img src={imagePath} alt="" />
  );
}

Это, однако, связывает все мои активы, несмотря ни на что.

Он загрузит правильное изображение, но все равно объединит все файлы в окончательной сборке.

Когда я смотрю на инструменты разработчика для окончательной сборки, я вижу все ресурсы там, хотя я только хотел загрузить ресурсы для app_1.

Я вынужден коснуться конфига webpack, если так, что я должен изменить? или есть другой способ?

Ответ 1

Вам нужно будет использовать Webpack (или другой Bundler.) Код не был запущен, когда он в комплекте, так что компилятор не имеет возможности узнать, какая ветвь логики следовать (app_1 или app_2). Поэтому вы должны войти в логику компоновщика, чтобы достичь своей цели.

Тем не менее, это не так страшно, как кажется, поскольку веб-пакет имеет встроенную возможность сделать это (не требуется никаких третьих лиц...)

Я хотел бы посмотреть на использование webpack.providePlugin

(https://webpack.js.org/plugins/provide-plugin)

или его родной брат DefinePlugin

(https://webpack.js.org/plugins/define-plugin)

(Боюсь, что эти примеры не в моей голове, поэтому очень маловероятно, что они сработают при первом проходе.)

Примеры:

Для обоих потребуется модуль провайдера...

// in path/provider.js

module.exports = {
  live: '/path/to/live/image',
  dev: '/path/to/dev/image'
}

Пример предоставления плагина

// in webpack

new webpack.ProvidePlugin({
    imagePath: [
      'path/provider',         // the file defined above
      process.env.ENVIRONMENT  // either 'dev' or 'live'
    ]
  }),
// in code

export default function Test() {
  return (
      <img src={imagePath} alt="" />
  );
}

Пример определения плагина:

// in webpack

new webpack.DefinePlugin({
  'process.env.ENVIRONMENT': JSON.stringify(process.env.ENVIRONMENT)
});
// in code

var providers = require('path/provider'); // same path provider as above

export default function Test() {
  return (
      <img src={providers[process.env.ENVIRONMENT]} alt="" />
  );
}

В обоих случаях компоновщик вынужден свернуть вашу переменную до фактического литерального значения во время компиляции - до того, как пакетирование произойдет. Поскольку теперь вы свернули логический путь до единого параметра, теперь можно свободно связывать только соответствующие активы.

Ответ 2

В те времена, когда React не существовало, мы не помещали ресурсы в наши файлы JS. Мы позволяем CSS решать, какие активы загружать для каких селекторов. Затем вы можете просто включить или выключить соответствующий класс для соответствующего элемента (или даже всей страницы) и изменить его, изменить цвет, фон или даже форму. Чистая магия!

Ах. Какие времена это были!

Все вышесказанное - правда, и я не понимаю, зачем кому-то делать или рекомендовать делать это иначе. Однако, если вы все еще хотите сделать это (по любой причине) - вы можете! Новейшее приложение create-react-app поставляется с готовой поддержкой отложенной загрузки произвольных компонентов посредством динамического импорта и разделения кода. Все, что вам нужно сделать, это использовать заключенную в скобки версию оператора import() вместо обычной. import() принимает строку запроса как обычно и возвращает Promise. Это. Исходный код динамически запрашиваемого компонента не будет упакован, а вместо этого сохранен в отдельных блоках для загрузки по требованию.

До:

import OtherComponent from './OtherComponent';

function MyComponent() {   
  return (
    <div>
      <OtherComponent />
    </div>   
  ); 
}

После:

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <OtherComponent />
    </div>
  );
}

Обратите внимание, как часть function MyComponent идентична.

Для тех, кто интересуется, связан ли он с CRA или React, это не так. Это общая концепция, которая может быть использована в ванильном JavaScript.

Ответ 3

Вы не можете сделать это с настройками CRA по умолчанию.

Поскольку, если ваш динамический запрос или динамический путь импорта не является статическим, веб-пакет не сможет определить, какие ресурсы следует включить в папку окончательной сборки, поэтому он будет ./src все из вашей папки ./src и помещать их все в свой каталог. build папку.