在 create-react-app 中有条件地导入资产
Conditionally import assets in create-react-app
在使用 create-react-app 创建 React 应用程序时是否可以有条件地导入资产?我知道 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 配置,如果是,我应该更改什么?或者有其他方法吗?
你将需要使用 webpack(或其他打包器)。代码在打包时没有被 运行,所以编译器无法知道哪个要遵循的逻辑分支(app_1 或 app_2)。因此,您必须了解打包程序的逻辑才能实现您的目标。
然而,这并不像看起来那么可怕,因为 webpack 内置了执行此操作的能力(不需要第 3 方...)
我会考虑使用 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="" />
);
}
在这两种情况下,捆绑器都被迫在编译时将您的变量折叠为实际的文字值 - 在捆绑发生之前。由于您现在已将逻辑路径折叠为单个选项,因此现在可以自由地仅捆绑相关资产。
在 React 不存在的日子里,我们没有将资产放入我们的 JS 文件中。我们让 CSS 决定为哪些选择器加载哪些资产。然后您可以简单地为相应元素( 甚至整个页面 )打开或关闭相应的 class,它会改变颜色、背景甚至表单。纯粹的魔法!
啊。这是什么时代啊!
以上都是正确的,我不明白为什么有人会做或建议做不同的事情。但是,如果您仍然想这样做(出于任何原因)——您可以!最新 create-react-app
附带对 lazy loading of arbitrary components via dynamic importing and code splitting 的开箱即用支持。您需要做的就是使用带括号的 import()
语句而不是常规语句。 import()
像往常一样接受请求字符串,returns 接受 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 相关的人来说,事实并非如此。 can be used in vanilla JavaScript 是一个通用概念。
您无法使用 默认 CRA 设置。
因为如果你的dynamic require或dynamic import路径不是static,webpack就赢了无法确定要包含在最终构建文件夹中的资产,因此,它将从您的 ./src
文件夹中获取所有内容,并将它们全部放入您的 build
文件夹中。
有一种方法可以使用 默认 CRA 设置
您可以向 .env 添加类似
的内容
REACT_APP_SKIN=1
将您的皮肤资产放入 public/css1、public/css2 等。然后使用类似
的代码将它们包含在 public/index.html 中
<link href="/css%REACT_APP_SKIN%/theme.css" rel="stylesheet">
在使用 create-react-app 创建 React 应用程序时是否可以有条件地导入资产?我知道 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 配置,如果是,我应该更改什么?或者有其他方法吗?
你将需要使用 webpack(或其他打包器)。代码在打包时没有被 运行,所以编译器无法知道哪个要遵循的逻辑分支(app_1 或 app_2)。因此,您必须了解打包程序的逻辑才能实现您的目标。
然而,这并不像看起来那么可怕,因为 webpack 内置了执行此操作的能力(不需要第 3 方...)
我会考虑使用 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="" />
);
}
在这两种情况下,捆绑器都被迫在编译时将您的变量折叠为实际的文字值 - 在捆绑发生之前。由于您现在已将逻辑路径折叠为单个选项,因此现在可以自由地仅捆绑相关资产。
在 React 不存在的日子里,我们没有将资产放入我们的 JS 文件中。我们让 CSS 决定为哪些选择器加载哪些资产。然后您可以简单地为相应元素( 甚至整个页面 )打开或关闭相应的 class,它会改变颜色、背景甚至表单。纯粹的魔法!
啊。这是什么时代啊!
以上都是正确的,我不明白为什么有人会做或建议做不同的事情。但是,如果您仍然想这样做(出于任何原因)——您可以!最新 create-react-app
附带对 lazy loading of arbitrary components via dynamic importing and code splitting 的开箱即用支持。您需要做的就是使用带括号的 import()
语句而不是常规语句。 import()
像往常一样接受请求字符串,returns 接受 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 相关的人来说,事实并非如此。 can be used in vanilla JavaScript 是一个通用概念。
您无法使用 默认 CRA 设置。
因为如果你的dynamic require或dynamic import路径不是static,webpack就赢了无法确定要包含在最终构建文件夹中的资产,因此,它将从您的 ./src
文件夹中获取所有内容,并将它们全部放入您的 build
文件夹中。
有一种方法可以使用 默认 CRA 设置
您可以向 .env 添加类似
的内容REACT_APP_SKIN=1
将您的皮肤资产放入 public/css1、public/css2 等。然后使用类似
的代码将它们包含在 public/index.html 中<link href="/css%REACT_APP_SKIN%/theme.css" rel="stylesheet">