在ReactJS应用程序中,如何将全局环境中的环境变量替换到我的index.html文件中?
我有一个ReactJS17应用程序,在其中我想将全局环境中的环境变量替换到我的在ReactJS应用程序中,如何将全局环境中的环境变量替换到我的index.html文件中?,reactjs,npm,environment-variables,Reactjs,Npm,Environment Variables,我有一个ReactJS17应用程序,在其中我想将全局环境中的环境变量替换到我的src/index.html文件中。然而,我们没有使用.env文件,正如这个答案所暗示的--。这是src/index.html文件 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content=&qu
src/index.html
文件中。然而,我们没有使用.env
文件,正如这个答案所暗示的--。这是src/index.html
文件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
...
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="512x512">
<script src="%REACT_APP_THIRD_PARTY_URL%"></script>
</head>
<body>
我正在开发模式下运行我的应用程序,使用npmi
安装,并使用npm run start
运行。但是,上面的替换从未进行过,页面将使用
<script src="%REACT_APP_THIRD_PARTY_URL%"></script>
编辑2:不确定这是否重要,但这在我的网页文件中
my package.json
{
"name": "my_app",
"version": "1.0.0",
"description": "My desc",
"main": "index.js",
"scripts": {
"test": "jest",
"test:watch": "jest --watchAll",
"test:coverage": "jest --coverage",
"build": "webpack --config webpack.production.js",
"start": "webpack-dev-server --open --config webpack.development.js",
...
这是webpack.development.js文件
require('dotenv').config();
const { merge } = require('webpack-merge');
const common = require('./webpack.common');
const WEBPACK_WATCH_POLLING = process.env.WEBPACK_WATCH_POLLING === '1';
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
publicPath: '/',
historyApiFallback: true,
disableHostCheck: true,
hot: true,
host: '0.0.0.0',
port: 8080,
},
output: {
publicPath: '/',
},
// This is needed for docker-on-windows.
watchOptions: !WEBPACK_WATCH_POLLING
? undefined
: {
poll: 1000,
},
});
这是我的webpack.common文件
module.exports = {
entry: './src/index.tsx',
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js', '.json', '.css', '.scss'],
alias: {
'@': path.resolve('src'),
'@sb': path.resolve('.storybook'),
'@static': path.resolve('static'),
common: path.resolve('src/components/common'),
},
},
module: {
rules: [
{
test: /\.(js|ts)x?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
babelrc: true,
},
},
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
},
],
},
{
test: /\.(scss|css)$/i,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.(jpe?g|gif|png)$/,
use: {
loader: 'url-loader',
},
},
{
test: /\.svg$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'icons/',
},
},
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/',
},
},
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
REACT_APP_THIRD_PARTY_URL: "http://google.com"
//filename: './index.html',
}),
new CopyWebpackPlugin({
patterns: [
{ from: 'src/manifest.json' },
{ from: 'static/**/*.{png,svg,ico}', flatten: true },
],
}),
new WorkboxWebpackPlugin.InjectManifest({
swSrc: './src/service-worker.js',
}),
new EnvironmentPlugin([
'NODE_ENV',
'REACT_APP_THIRD_PARTY_URL',
]),
],
};
最后,我的src/index.tsx文件
import './monitor';
import * as serviceWorker from './sw-registration';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/app/App';
import './i18n.js';
ReactDOM.render(
<React.StrictMode>
<React.Suspense fallback={<div>Loading...</div>}>
<App />
</React.Suspense>
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.register();
import./monitor';
从“/sw注册”导入*作为serviceWorker;
从“React”导入React;
从“react dom”导入react dom;
从“./components/App/App”导入应用程序;
导入“/i18n.js”;
ReactDOM.render(
,
document.getElementById('root'))
);
register();
根据您的环境和构建工具,有几种可能的方法
我认为对您来说,最方便的方法是在构建时将它们提供给您的项目
index.html
文件(通过使用模板引擎或为您执行作业的简单脚本),并通过从环境中读取所需变量来手动追加所需变量webpack
构建捆绑包,则可以使用HtmlWebpackPlugin
为您构建index.html
文件,其中包含所需的所有环境数据.ejs
或.html
文件,用作模板:
<!DOCTYPE html>
<html>
<head>
...
<script src="<%= htmlWebpackPlugin.options.thirdPartyData.url %>"></script>
</head>
<body></body>
</html>
Webpack
将从环境中获取变量(通过节点
),并基于模板文件为您构建索引.html
。您可以向插件提供任意数据,然后可以从htmlWebpackPlugin.options
属性的模板中读取这些数据。你可以了解更多关于
请注意,为了更改代码本身中的环境变量,您必须通过webpack
进行重建,这是可以理解的
此解决方案不需要您使用create react app
或.env
文件,也不需要服务器/服务器渲染来为您执行此任务。请注意,它也完全在react应用程序的上下文之外工作(您不在react应用程序本身中,而是直接在.html
标记上工作)
另一种可能的方法是使用
--env
标志,通过npm脚本
提供环境变量,但这将不方便您进行集成,因为它需要一些额外的工作
评论后编辑: 这是一本书。由于codesandbox本身执行脚本的方式,提供的代码在codesandbox内部不起作用,但如果您在计算机上复制提供的示例,它将执行它应该执行的操作。为了测试它,您只需要
index.html
、webpack.config.json
、package.json
和一个虚拟的index.js
。为了简洁起见,我已经删除了与react相关的代码
只需下载codesandbox示例,运行npm安装
,然后npm启动
然后可以将该方法迁移到特定的代码库
编辑2: 好吧,我发现了问题。您的
html加载程序
会干扰HtmlWebpackPlugin
,并且不会替换模板中的变量。如果在webpack.config中注释掉html加载程序
,您会注意到转换是有效的。因此,最简单的解决方案是:
index.html.ejs
文件,并将其放在index.html
旁边。这是一个实际正确的ejs
模板。将index.html的当前内容放在那里:
index.html.ejs
:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="512x512">
<script src="<%= htmlWebpackPlugin.options.REACT_APP_THIRD_PARTY_URL %>"></script>
...
</head>
<body>
...
</body>
</html>
此时,您甚至可以完全删除index.html
,因为它将由HtmlWebpackPlugin
插件生成
通过这种方式,您可以保留html加载程序
转换(如果您真的需要它做任何事情),并获得插入的html文件。您可以在shell中添加程序包管理器(npm或Thread)可用于构建React应用程序的程序包
您可以通过以下方式完成:
$REACT\u APP\u第三方\u URL=http://thirdpartyurl.com npm启动
或
$REACT\u APP\u THIRD\u PARTY\u URL=$REACT\u APP\u THIRD\u PARTY\u URL npm start
假设“REACT\u APP\u THIRD\u PARTY\u URL”定义为全局环境变量(打印$echo$REACT\u APP\u THIRD\u PARTY\u URL的值
)
您可以类似地运行其他npm/THEAN命令,如“build”、“test”等,它将替换HTML中的值(
)
使用不同的操作系统时会有细微的差别。以上示例适用于shell
编辑:
如果您不想每次使用npm start或build命令编写这些长环境变量,可以在package.json中编写:
“脚本”:{
“开始”:“REACT\u APP\u THIRD\u PARTY\u URL=$REACT\u APP\u THIRD\u PARTY\u URL REACT\u APP\u other\u VAR=$REACT\u APP\u other\u VAR REACT scripts start”,
...
}
如果您使用的不是react脚本,而是webpack dev serverdi
<!DOCTYPE html>
<html>
<head>
...
<script src="<%= htmlWebpackPlugin.options.thirdPartyData.url %>"></script>
</head>
<body></body>
</html>
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: '<PATH_TO_YOUR_TEMPLATE>',
thirdPartyData: {
url: process.env.<YOUR_ENV_VARIABLE>
}
})
]
};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="512x512">
<script src="<%= htmlWebpackPlugin.options.REACT_APP_THIRD_PARTY_URL %>"></script>
...
</head>
<body>
...
</body>
</html>
new HtmlWebpackPlugin({
template: './src/index.html.ejs',
REACT_APP_THIRD_PARTY_URL: "http://google.com"
})