[英]Passing environment-dependent variables in webpack
I'm trying to convert an angular app from gulp to webpack.我正在尝试将 Angular 应用程序从 gulp 转换为 webpack。 in gulp I use gulp-preprocess to replace some variables in the html page (eg database name) depending on the NODE_ENV.在 gulp 中,我使用 gulp-preprocess 替换 html 页面中的一些变量(例如数据库名称),具体取决于 NODE_ENV。 What is the best way of achieving a similar result with webpack?使用 webpack 实现类似结果的最佳方法是什么?
There are two basic ways to achieve this.有两种基本方法可以实现这一目标。
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
}),
Note that this will just replace the matches "as is".请注意,这只会“按原样”替换匹配项。 That's why the string is in the format it is.这就是为什么字符串是它的格式。 You could have a more complex structure, such as an object there but you get the idea.你可以有一个更复杂的结构,比如一个对象,但你明白了。
new webpack.EnvironmentPlugin(['NODE_ENV'])
EnvironmentPlugin
uses DefinePlugin
internally and maps the environment values to code through it. EnvironmentPlugin
在内部使用DefinePlugin
并通过它将环境值映射到代码。 Terser syntax.更简洁的语法。
Alternatively you could consume configuration through an aliased module .或者,您可以通过别名模块使用配置。 From consumer side it would look like this:从消费者方面来看,它看起来像这样:
var config = require('config');
Configuration itself could look like this:配置本身可能如下所示:
resolve: {
alias: {
config: path.join(__dirname, 'config', process.env.NODE_ENV)
}
}
Let's say process.env.NODE_ENV
is development
.假设process.env.NODE_ENV
是development
。 It would map into ./config/development.js
then.然后它将映射到./config/development.js
。 The module it maps to can export configuration like this:它映射到的模块可以像这样导出配置:
module.exports = {
testing: 'something',
...
};
Just another option, if you want to use only a cli interface, just use the define
option of webpack.只是另一种选择,如果您只想使用 cli 接口,只需使用 webpack 的define
选项。 I add the following script in my package.json
:我在package.json
中添加以下脚本:
"build-production": "webpack -p --define process.env.NODE_ENV='\"production\"' --progress --colors"
So I just have to run npm run build-production
.所以我只需要运行npm run build-production
。
I investigated a couple of options on how to set environment-specific variables and ended up with this:我研究了几个关于如何设置环境特定变量的选项,最终得到了这个:
I have 2 webpack configs currently:我目前有 2 个 webpack 配置:
webpack.production.config.js webpack.production.config.js
new webpack.DefinePlugin({
'process.env':{
'NODE_ENV': JSON.stringify('production'),
'API_URL': JSON.stringify('http://localhost:8080/bands')
}
}),
webpack.config.js webpack.config.js
new webpack.DefinePlugin({
'process.env':{
'NODE_ENV': JSON.stringify('development'),
'API_URL': JSON.stringify('http://10.10.10.10:8080/bands')
}
}),
In my code I get the value of API_URL in this (brief) way:在我的代码中,我以这种(简要)方式获得 API_URL 的值:
const apiUrl = process.env.API_URL;
EDIT 3rd of Nov, 2016编辑 2016 年 11 月 3 日
Webpack docs has an example: https://webpack.js.org/plugins/define-plugin/#usage Webpack 文档有一个例子: https ://webpack.js.org/plugins/define-plugin/#usage
new webpack.DefinePlugin({
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify("5fa3b9"),
BROWSER_SUPPORTS_HTML5: true,
TWO: "1+1",
"typeof window": JSON.stringify("object")
})
With ESLint you need to specifically allow undefined variables in code, if you have no-undef
rule on.使用ESLint ,如果您有no-undef
规则,您需要在代码中明确允许未定义的变量。 http://eslint.org/docs/rules/no-undef like this: http://eslint.org/docs/rules/no-undef像这样:
/*global TWO*/
console.log('Running App version ' + TWO);
EDIT 7th of Sep, 2017 (Create-React-App specific)编辑 2017 年 9 月 7 日(特定于 Create-React-App)
If you're not into configuring too much, check out Create-React-App: Create-React-App - Adding Custom Environment Variables .如果您不想配置太多,请查看 Create-React-App: Create-React-App - 添加自定义环境变量。 Under the hood CRA uses Webpack anyway.无论如何,CRA 在幕后使用 Webpack。
You can pass environment variables without additional plugins using --env
您可以使用--env
传递环境变量而无需其他插件
webpack --config webpack.config.js --env.foo=bar
Webpack 5+ (without .
) Webpack 5+ (没有.
)
webpack --config webpack.config.js --env foo=bar
Then, use the variable in webpack.config.js
:然后,使用webpack.config.js
中的变量:
module.exports = function(env) {
if (env.foo === 'bar') {
// do something
}
}
Further Reading : Webpack 2.0 doesn't support custom command line arguments?进一步阅读: Webpack 2.0 不支持自定义命令行参数? #2254 #2254
You can directly use the EnvironmentPlugin
available in webpack
to have access to any environment variable during the transpilation.您可以直接使用webpack
中提供的EnvironmentPlugin
在转译期间访问任何环境变量。
You just have to declare the plugin in your webpack.config.js
file:您只需在webpack.config.js
文件中声明插件:
var webpack = require('webpack');
module.exports = {
/* ... */
plugins: [
new webpack.EnvironmentPlugin(['NODE_ENV'])
]
};
Note that you must declare explicitly the name of the environment variables you want to use.请注意,您必须明确声明要使用的环境变量的名称。
To add to the bunch of answers personally I prefer the following:为了个人添加到一堆答案中,我更喜欢以下内容:
const webpack = require('webpack');
const prod = process.argv.indexOf('-p') !== -1;
module.exports = {
...
plugins: [
new webpack.DefinePlugin({
process: {
env: {
NODE_ENV: prod? `"production"`: '"development"'
}
}
}),
...
]
};
Using this there is no funky env variable or cross-platform problems (with env vars).使用它没有时髦的环境变量或跨平台问题(使用环境变量)。 All you do is run the normal webpack
or webpack -p
for dev or production respectively.您所做的只是分别为开发或生产运行正常的webpack
或webpack -p
。
Reference: Github issue参考: Github问题
Since my Edit on the above post by thevangelist wasn't approved , posting additional information.由于我对thevangelist 的上述帖子的编辑未获批准,因此发布了其他信息。
If you want to pick value from package.json like a defined version number and access it through DefinePlugin inside Javascript.如果您想从package.json中提取值,例如定义的版本号,并通过 Javascript 中的DefinePlugin访问它。
{"version": "0.0.1"}
Then, Import package.json inside respective webpack.config , access the attribute using the import variable, then use the attribute in the DefinePlugin .然后,在各自的webpack.config中导入package.json ,使用导入变量访问属性,然后使用DefinePlugin中的属性。
const PACKAGE = require('../package.json');
const _version = PACKAGE.version;//Picks the version number from package.json
For example certain configuration on webpack.config is using METADATA for DefinePlugin:例如webpack.config上的某些配置使用元数据作为 DefinePlugin:
const METADATA = webpackMerge(commonConfig({env: ENV}).metadata, {
host: HOST,
port: PORT,
ENV: ENV,
HMR: HMR,
RELEASE_VERSION:_version//Version attribute retrieved from package.json
});
new DefinePlugin({
'ENV': JSON.stringify(METADATA.ENV),
'HMR': METADATA.HMR,
'process.env': {
'ENV': JSON.stringify(METADATA.ENV),
'NODE_ENV': JSON.stringify(METADATA.ENV),
'HMR': METADATA.HMR,
'VERSION': JSON.stringify(METADATA.RELEASE_VERSION)//Setting it for the Scripts usage.
}
}),
Access this inside any typescript file:在任何打字稿文件中访问它:
this.versionNumber = process.env.VERSION;
The smartest way would be like this:最聪明的方法是这样的:
// webpack.config.js
plugins: [
new webpack.DefinePlugin({
VERSION: JSON.stringify(require("./package.json").version)
})
]
Just another answer that is similar to @zer0chain's answer.只是另一个类似于@ zer0chain 的答案的答案。 However, with one distinction.但是,有一个区别。
webpack -p
is sufficient.设置webpack -p
就足够了。It is the same as:它与以下内容相同:
--define process.env.NODE_ENV="production"
And this is the same as这与
// webpack.config.js
const webpack = require('webpack');
module.exports = {
//...
plugins:[
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
]
};
So you may only need something like this in package.json
Node file:所以你可能只需要在package.json
节点文件中这样的东西:
{
"name": "projectname",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"debug": "webpack -d",
"production": "webpack -p"
},
"author": "prosti",
"license": "ISC",
"dependencies": {
"webpack": "^2.2.1",
...
}
}
Just a few tips from the DefinePlugin :来自DefinePlugin的一些提示:
The DefinePlugin allows you to create global constants which can be configured at compile time. DefinePlugin 允许您创建可以在编译时配置的全局常量。 This can be useful for allowing different behavior between development builds and release builds.这对于允许开发构建和发布构建之间的不同行为很有用。 For example, you might use a global constant to determine whether logging takes place;例如,您可以使用全局常量来确定是否发生日志记录; perhaps you perform logging in your development build but not in the release build.也许您在您的开发版本中执行日志记录,而不是在发布版本中。 That's the sort of scenario the DefinePlugin facilitates.这就是 DefinePlugin 促成的那种场景。
That this is so you can check if you type webpack --help
这样你就可以检查你是否输入webpack --help
Config options:
--config Path to the config file
[string] [default: webpack.config.js or webpackfile.js]
--env Enviroment passed to the config, when it is a function
Basic options:
--context The root directory for resolving entry point and stats
[string] [default: The current directory]
--entry The entry point [string]
--watch, -w Watch the filesystem for changes [boolean]
--debug Switch loaders to debug mode [boolean]
--devtool Enable devtool for better debugging experience (Example:
--devtool eval-cheap-module-source-map) [string]
-d shortcut for --debug --devtool eval-cheap-module-source-map
--output-pathinfo [boolean]
-p shortcut for --optimize-minimize --define
process.env.NODE_ENV="production"
[boolean]
--progress Print compilation progress in percentage [boolean]
I found the following solution to be easiest to setup environment variable for Webpack 2:我发现以下解决方案最容易为 Webpack 2 设置环境变量:
For example we have a webpack settings:例如我们有一个 webpack 设置:
var webpack = require('webpack')
let webpackConfig = (env) => { // Passing envirmonment through
// function is important here
return {
entry: {
// entries
},
output: {
// outputs
},
plugins: [
// plugins
],
module: {
// modules
},
resolve: {
// resolves
}
}
};
module.exports = webpackConfig;
Add Environment Variable in Webpack:在 Webpack 中添加环境变量:
plugins: [
new webpack.EnvironmentPlugin({
NODE_ENV: 'development',
}),
]
Define Plugin Variable and add it to plugins
:定义插件变量并将其添加到plugins
:
new webpack.DefinePlugin({
'NODE_ENV': JSON.stringify(env.NODE_ENV || 'development')
}),
Now when running webpack command, pass env.NODE_ENV
as argument:现在在运行 webpack 命令时,将env.NODE_ENV
作为参数传递:
webpack --env.NODE_ENV=development
// OR
webpack --env.NODE_ENV development
Now you can access NODE_ENV
variable anywhere in your code.现在您可以在代码中的任何位置访问NODE_ENV
变量。
I prefer using .env file for different environment.我更喜欢将 .env 文件用于不同的环境。
env.dev
to .env into root folder使用 webpack.dev.config 将env.dev
复制到 .env 到根文件夹env.prod
to .env使用 webpack.prod.config 将env.prod
复制到 .envand in code并在代码中
use利用
require('dotenv').config(); const API = process.env.API ## which will store the value from .env file
To add to the bunch of answers:添加到一堆答案:
Use ExtendedDefinePlugin instead of DefinePlugin使用ExtendedDefinePlugin而不是 DefinePlugin
npm install extended-define-webpack-plugin --save-dev.
ExtendedDefinePlugin is much simpler to use and is documented :-) link ExtendedDefinePlugin 使用起来更简单,并且有文档记录:-)链接
Because DefinePlugin lacks good documentation, I want to help out, by saying that it actually works like #DEFINE in c# .因为 DefinePlugin缺乏良好的文档,我想帮忙,说它实际上像c# 中的 #DEFINE一样工作。
#if (DEBUG)
Console.WriteLine("Debugging is enabled.");
#endif
Thus, if you want to understand how DefinePlugin works, read the c# #define doucmentation.因此,如果您想了解 DefinePlugin 的工作原理,请阅读 c# #define 文档。 link关联
My workaround for the webpack version "webpack": "^4.29.6"
is very simple.我对 webpack 版本"webpack": "^4.29.6"
的解决方法非常简单。
//package.json
{
...
"scripts": {
"build": "webpack --mode production",
"start": "webpack-dev-server --open --mode development"
},
}
you can pass --mode parameter with your webpack commnad then in webpack.config.js您可以使用 webpack commnad 传递 --mode 参数,然后在 webpack.config.js 中
// webpack.config.json
module.exports = (env,argv) => {
return {
...
externals: {
// global app config object
config: JSON.stringify({
apiUrl: (argv.mode==="production") ? '/api' : 'localhost:3002/api'
})
}
}
And I use baseurl in my code like this我像这样在我的代码中使用 baseurl
// my api service
import config from 'config';
console.log(config.apiUrl) // like fetch(`${config.apiUrl}/users/user-login`)
Here is a way that has worked for me and has allowed me keep my environment variables DRY by reusing a json file.这是一种对我有用的方法,它允许我通过重用 json 文件来保持环境变量 DRY。
const webpack = require('webpack');
let config = require('./settings.json');
if (__PROD__) {
config = require('./settings-prod.json');
}
const envVars = {};
Object.keys(config).forEach((key) => {
envVars[key] = JSON.stringify(config[key]);
});
new webpack.DefinePlugin({
'process.env': envVars
}),
Since Webpack v4, simply setting mode
in your Webpack config will set the NODE_ENV
for you (via DefinePlugin
).从 Webpack v4 开始,只需在 Webpack 配置中设置mode
即可为您设置NODE_ENV
(通过DefinePlugin
)。 Docs here.文档在这里。
A secure webpack plugin that supports dotenv and other environment variables and only exposes what you choose and use.一个安全的 webpack 插件,支持 dotenv 和其他环境变量,只公开你选择和使用的内容。
with some workaround with configuration based on defaults
option to achieve that, once the package has .env.defaults
file to as initial values for env variables you can use it for development
and let .env
for your production.通过基于defaults
选项的配置的一些解决方法来实现这一点,一旦包将.env.defaults
文件作为 env 变量的初始值,您就可以将其用于development
,并让.env
用于您的生产。
npm install dotenv-webpack --save-dev
.env.defaults
file创建一个.env.defaults
文件API_URL='dev_url/api/'
.env
file leave it empty, let defaults
works, update it on your deploy process创建一个.env
文件将其留空,让defaults
起作用,在部署过程中更新它webpack
- webpack.config.js
配置webpack
- webpack.config.js
new Dotenv({
defaults: true
})
file.js
开发环境测试file.js
console.log(process.env.API_URL)
// Outputs: dev_url/api/
.env
file在构建时,更新空.env
文件API_URL='prod_url/api/'
dotenv-webpack will use this to and override env.defaults
dotenv-webpack 将使用它来覆盖env.defaults
file.js
prod环境测试file.js
console.log(process.env.API_URL)
// Outputs: prod_url/api/
dotenv-webpack dotenv-webpack
dotenv-defaults dotenv-defaults
I'm not a huge fan of...我不是...的忠实粉丝
new webpack.DefinePlugin({
'process.env': envVars
}),
...as it does not provides any type of security. ...因为它不提供任何类型的安全性。 instead, you end up boosting your secret stuff, unless you add a webpack to gitignore 🤷♀️ there is a better solution.相反,您最终会增加您的秘密内容,除非您将 webpack 添加到 gitignore 🤷♀️ 有更好的解决方案。
Basically with this config once you compile your code all the process env variables will be removed from the entire code, there is not going to be a single process.env.VAR up thanks to the babel plugin transform-inline-environment-variables
PS if you do not want to end up with a whole bunch of undefines, make sure you call the env.js before webpack calls babel-loader, that's why it is the first thing webpack calls.基本上有了这个配置,一旦你编译了你的代码,所有进程环境变量都将从整个代码中删除,由于 babel 插件transform-inline-environment-variables
PS if,不会有一个 process.env.VAR 了你不想以一大堆未定义结束,请确保在 webpack 调用 babel-loader 之前调用 env.js,这就是为什么它是 webpack 调用的第一件事。 the array of vars in babel.config.js file must match the object on env.js. babel.config.js 文件中的变量数组必须与 env.js 上的对象匹配。 now there is only one mow thing to do.现在只有一件事情要做。 add a .env
file put all your env variables there, the file must be at the root of the project or feel free to add it where ever u want, just make sure to set the same location on the env.js file and also add it to gitignore添加一个.env
文件将所有环境变量放在那里,该文件必须位于项目的根目录下,或者随意添加它,只要确保在 env.js 文件上设置相同的位置并添加它到 gitignore
const dotFiles = ['.env'].filter(Boolean);
if (existsSync(dotFiles)) {
require("dotenv-expand")(require("dotenv").config((dotFiles)));
}
If you want to see the whole babel + webpack + ts get it from heaw https://github.com/EnetoJara/Node-typescript-babel-webpack.git
如果您想查看整个 babel + webpack + ts,请从 heaw https://github.com/EnetoJara/Node-typescript-babel-webpack.git
获取
and same logic applies to react and all the other 💩同样的逻辑适用于反应和所有其他💩
config
---webpack.js
---env.js
src
---source code world
.env
bunch of dotFiles
env.js环境.js
"use strict";
/***
I took the main idea from CRA, but mine is more cooler xD
*/
const {realpathSync, existsSync} = require('fs');
const {resolve, isAbsolute, delimiter} = require('path');
const NODE_ENV = process.env.NODE_ENV || "development";
const appDirectory = realpathSync(process.cwd());
if (typeof NODE_ENV !== "string") {
throw new Error("falle and stuff");
}
const dotFiles = ['.env'].filter(Boolean);
if (existsSync(dotFiles)) {
require("dotenv-expand")(require("dotenv").config((dotFiles)));
}
process.env.NODE_PATH = (process.env.NODE_PATH || "")
.split(delimiter)
.filter(folder => folder && isAbsolute(folder))
.map(folder => resolve(appDirectory, folder))
.join(delimiter);
const ENETO_APP = /^ENETO_APP_/i;
module.exports = (function () {
const raw = Object.keys ( process.env )
.filter ( key => ENETO_APP.test ( key ) )
.reduce ( ( env, key ) => {
env[ key ] = process.env[ key ];
return env;
},
{
BABEL_ENV: process.env.ENETO_APP_BABEL_ENV,
ENETO_APP_DB_NAME: process.env.ENETO_APP_DB_NAME,
ENETO_APP_DB_PASSWORD: process.env.ENETO_APP_DB_PASSWORD,
ENETO_APP_DB_USER: process.env.ENETO_APP_DB_USER,
GENERATE_SOURCEMAP: process.env.ENETO_APP_GENERATE_SOURCEMAP,
NODE_ENV: process.env.ENETO_APP_NODE_ENV,
PORT: process.env.ENETO_APP_PORT,
PUBLIC_URL: "/"
} );
const stringyField = {
"process.env": Object.keys(raw).reduce((env, key)=> {
env[key]=JSON.stringify(raw[key]);
return env;
},{}),
};
return {
raw, stringyField
}
})();
webpack file with no plugins troll没有插件的 webpack 文件
"use strict";
require("core-js");
require("./env.js");
const path = require("path");
const nodeExternals = require("webpack-node-externals");
module.exports = env => {
return {
devtool: "source-map",
entry: path.join(__dirname, '../src/dev.ts'),
externals: [nodeExternals()],
module: {
rules: [
{
exclude: /node_modules/,
test: /\.ts$/,
use: [
{
loader: "babel-loader",
},
{
loader: "ts-loader"
}
],
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: "file-loader",
},
],
},
],
},
node: {
__dirname: false,
__filename: false,
},
optimization: {
splitChunks: {
automaticNameDelimiter: "_",
cacheGroups: {
vendor: {
chunks: "initial",
minChunks: 2,
name: "vendor",
test: /[\\/]node_modules[\\/]/,
},
},
},
},
output: {
chunkFilename: "main.chunk.js",
filename: "name-bundle.js",
libraryTarget: "commonjs2",
},
plugins: [],
resolve: {
extensions: ['.ts', '.js']
} ,
target: "node"
};
};
babel.config.js babel.config.js
module.exports = api => {
api.cache(() => process.env.NODE_ENV);
return {
plugins: [
["@babel/plugin-proposal-decorators", { legacy: true }],
["@babel/plugin-transform-classes", {loose: true}],
["@babel/plugin-external-helpers"],
["@babel/plugin-transform-runtime"],
["@babel/plugin-transform-modules-commonjs"],
["transform-member-expression-literals"],
["transform-property-literals"],
["@babel/plugin-transform-reserved-words"],
["@babel/plugin-transform-property-mutators"],
["@babel/plugin-transform-arrow-functions"],
["@babel/plugin-transform-block-scoped-functions"],
[
"@babel/plugin-transform-async-to-generator",
{
method: "coroutine",
module: "bluebird",
},
],
["@babel/plugin-proposal-async-generator-functions"],
["@babel/plugin-transform-block-scoping"],
["@babel/plugin-transform-computed-properties"],
["@babel/plugin-transform-destructuring"],
["@babel/plugin-transform-duplicate-keys"],
["@babel/plugin-transform-for-of"],
["@babel/plugin-transform-function-name"],
["@babel/plugin-transform-literals"],
["@babel/plugin-transform-object-super"],
["@babel/plugin-transform-shorthand-properties"],
["@babel/plugin-transform-spread"],
["@babel/plugin-transform-template-literals"],
["@babel/plugin-transform-exponentiation-operator"],
["@babel/plugin-proposal-object-rest-spread"],
["@babel/plugin-proposal-do-expressions"],
["@babel/plugin-proposal-export-default-from"],
["@babel/plugin-proposal-export-namespace-from"],
["@babel/plugin-proposal-logical-assignment-operators"],
["@babel/plugin-proposal-throw-expressions"],
[
"transform-inline-environment-variables",
{
include: [
"ENETO_APP_PORT",
"ENETO_APP_NODE_ENV",
"ENETO_APP_BABEL_ENV",
"ENETO_APP_DB_NAME",
"ENETO_APP_DB_USER",
"ENETO_APP_DB_PASSWORD",
],
},
],
],
presets: [["@babel/preset-env",{
targets: {
node: "current",
esmodules: true
},
useBuiltIns: 'entry',
corejs: 2,
modules: "cjs"
}],"@babel/preset-typescript"],
};
};
now 2020, i am face to same question, but for this old question, there are so many new answer, just list some of it:现在是 2020 年,我面临同样的问题,但是对于这个老问题,有很多新答案,只列出一些:
plugins: [
new HtmlWebpackPlugin({
// 1. title is the parameter, you can use in ejs template
templateParameters:{
title: JSON.stringify(someting: 'something'),
},
}),
//2. BUILT_AT is a parameter too. can use it.
new webpack.DefinePlugin({
BUILT_AT: webpack.DefinePlugin.runtimeValue(Date.now,"some"),
}),
//3. for webpack5, you can use global variable: __webpack_hash__
//new webpack.ExtendedAPIPlugin()
],
//4. this is not variable, this is module, so use 'import tt' to use it.
externals: {
'ex_title': JSON.stringify({
tt: 'eitentitle',
})
},
the 4 ways only basic, there are even more ways that i believe.这4种方式只是基本的,我相信还有更多的方式。 but i think maybe this 4ways is the most simple.但我认为也许这 4ways 是最简单的。
I don't know why but nobody really mentioning the simplest solution. 我不知道为什么,但是没有人真正提到最简单的解决方案。 This works for me for nodejs and grunt. 这对我来说适用于nodejs和grunt。 As for many people the webpack can be confusing you can simply use the below line: 对于许多人来说,Webpack可能会使您感到困惑,您只需使用以下行即可:
process.env.NODE_ENV = 'production';
With the above solution you don't really need to use envify or webpack. 使用上述解决方案,您实际上不需要使用envify或webpack。 Sometimes the simple hardcoded solution may work for some people. 有时,简单的硬编码解决方案可能对某些人有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.