Условно импортировать активы в приложение 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
папку.