29 webpack中的环境变量

环境变量

使用Webpack构建项目的时候,往往会区分环境进行不同的构建,比如生产环境和开发环境。项目在上线之前,还需要进入测试环境,进行系统功能的检测,那么就又多了一个或者多个测试环境,不同的环境构建功能肯定是有区别的。

大多数情况下,不同环境之间的配置还是有复用性的,只有少数的地方是因环境不同而变化的,使用环境变量就可以消除不同环境的配置差异,极大的复用我们的配置。本章节将针对Wabpack中涉及到的各种环境变量的定义,使用进行介绍。

环境对象(Environment)

当Webpack配置导出一个函数的时候,该函数会被传入一个环境对象,当我们使用npm scripts运行一个shell命令的时候,我们可以给这个环境对象设置相应的值。示例配置如下:

module.exports = function (env) {
    
    
    const {
    
     prod = 'dev' } = env || {
    
    };
    return {
    
    
        entry: entryPath[prod],
        output: {
    
    
            path: path.resolve(__dirname, outputPath[prod])
        },
        plugins: [
            new HtmlwebpackPlugin({
    
    
                template: './src/index.html'
            })
        ]
    }
}

还需在package.json中的scripts字段中做如下配置:

{
    
    
    "scripts": {
    
    
        "dev": "node ./scripts/dev.js",
        "build:gamma": "webpack --env.prod=gamma",
        "build:uat": "webpack --env.prod=uat",
        "build:prod": "webpack --env.prod=prod"
    }
}

该配置根据env中prod的值不同,采用不用的入口文件,从而产生不同的构建结果。美中不足的是,设置了环境变量对象,其中的值只能在Webpack的配置文件中使用,无法在项目文件中(这里指的是在浏览器运行的Web项目,下面简称项目文件)进行使用,局限性较大。

Process.env

Webpack是基于Node.js而产生的,因为Webpack依赖于Node环境,所以Node.js相关的API和一些全局属性都可以在Webpack中直接使用。其中Process模块是Node中的一个全局模块,它始终可以供Node.js程序使用。Process代表一个Node程序的主进程,其提供了很多功能强大的API,让我们可以和操作系统实现互动。

Process.env是Process的一个环境属性,其值是一个对象,默认值是一个空对象。用Webpack构建的项目经常能见到它的身影,与上一节介绍的Webpack中的环境对象不同,该对象可以在项目文件中使用。

Webpack中mode的配置就会为process.env设置对应的NODE_ENV属性,该属性的值取决于mode的值。如下配置:

module.exports = {
    
    
    mode: 'development',
    plugins: [
        new HtmlwebpackPlugin(),
    ]
}

将mode设置为development,然后在入口文件中输出process.env.NODE_ENV,控制台显示development。将mode设置为production或者none,process.env.NODE_ENV的值也会发生对应的改变。开发者可以根据process.env.NODE_ENV的值对自己的程序做出改变。同时使用下面的脚本命令也可以得到同样的效果:

{
    
    
    "scripts": {
    
    
        "dev": "node ./scripts/dev.js",
        "build": "webpack --mode=production"
    }
}

其中"webpack --mode=production"可以简写为"webpack",执行命令"webpack"构建时process.env.NODE_ENV的值恒为produciton。

值得注意的是,正常情况下process.env.NODE_ENV无法在webpack中的配置文件中获取,当你尝试使用process.env.NODE_ENV的用于webpack配置文件的时候,你会得到一个undefined,使用Cross-env模块,就可以解决该问题。

Cross-env模块能够提供一个设置环境变量的scripts,让你能够以unix方式设置环境变量,然后在windows上也能兼容运行。也就是可以使用该模块可以跨平台的设置环境变量。引入Cross-env之后,配置如下:

const prod = process.env.NODE_ENV === 'production';

module.exports = {
    
    
    mode: prod ? 'production' : 'development',
    plugins: [
        new HtmlwebpackPlugin(),
    ]
}

package.json中scripts字段配置如下:

{
    
    
    "scripts": {
    
    
        "dev": "node ./scripts/dev.js",
        "build": "webpack --mode=production",
        "build:prod": "cross-env NODE_ENV=production webpack --mode=production",
        "build:dev": "cross-env NODE_ENV=develoment webpack --mode=development"
    }
}

现在在项目文件和Webpack配置文件中均可使用process.env.NODE_ENV的值。

命令行参数

当我们使用Node运行一个JavaScript脚本的时候,我们可以在运行的命令中添加各种参数,这个参数就叫做命令行参数.比如:node ./test.js name=render。name=render就是我们传递的参数。运行的JavaScript脚本可以通过相应的操作获取命令行参数,通过参数来动态修改程序的逻辑,从而改变运行结果。

Process.argv和yargs都是可以用来接收命令行参数的,下面对它们进行一一介绍。

Process.argv

使用process.argv可以获取命令行的参数,其值无法在项目文件中使用。其值是一个数组,数组的第一项和第二项分别代表node的执行文件所在位置和当前js脚本文件所在的位置,所以一般获取命令行参数的写法如下:

const argvs = process.argv.splice(2);

当命令为:node test.js name=render age=18的时候,argvs的值为:[ ‘name=render’, ‘age=18’ ]。

Yargs

Yargs是一个功能十分强大的Node模块,在这里只对其如何接收命令行参数做介绍。使用yargs获取node命令参数时,参数名需以 – 开头,中间使用 = 或 空格,然后接上值,才可以获取到参数的值:

const yargs = require('yargs');
console.log(yargs.argv.name);
console.log(yargs.argv.age);

输入命令: node test.js --name render --age=18
输出结果为:render 18
如果参数不以–开头,如下命令:
node test.js --name render --age=18 job=xxx
可以通过yargs.argv._获取job=xxx参数,如果写成-job=xxx,那么yargs.argv._不会有该值的存在。

使用NodeJS.API构建

之前我们在进行构建的时候,我们使用的是Webpack中的webpack命令进行构建,命令行参数是Node命令中的,把两者进行关联将会使得我们的配置更加灵活更加强大。

总体实现步骤就是使用node运行一个脚本文件,该脚本的功能来执行Webpack的构建操作。中间脚本文件则可以获取命令行参数,从而修改Webpack的构建结果。

脚本代码如下所示:

const webpack = require('webpack');
const webpackConfig = require('../webpack.config');
const compiler = webpack(webpackConfig);

compiler.run((...argv) => {
    
    
    console.log(argv);
});

引入webpack模块(webpack模块本身就是一个可执行模块),其导出一个函数,然后将配置文件中的内容作为入参传入得到一个Compller对象。其中Compiler就是Webpack中的一个编译对象,其内置了许多API和属性,使用其run方法,就可以代替使用webpack命令来执行构建的操作。之后只需要使用node ./srcipts/build.js命令,就可以实现构建操作,此时可以传入相应的命令参数,根据命令行参数对构建做一些额外的操作。

使用Dotenv

之前学习了如何给process.env添加NODE_ENV,使得process.env.NODE_ENV能在全局使用。如果你想在项目中使用类似于process.env.NODE_ENV这种全局变量,你可以使用Webpack内置的DefinePlugin插件,该插件允许创建一个在编译时可以配置的全局常量,如下所示:

module.exports = {
    
    
    plugins: [
        new HtmlwebpackPlugin(),
        new webpack.DefinePlugin({
    
    
            "process.env.REACT_ENV": JSON.stringify('production'),
            "GLOBAL_NAME": JSON.stringify("render")
        })
    ]
}

现在process.env.REACT_EN和GLOBAL_NAME已经全局可用,比如在项目入口文件输出对应的值:

console.log(process.env.REACT_ENV);
console.log(GLOBAL_NAME);

可以根据不同环境动态改变其值,达到改变程序运行的结果,如下所示:

module.exports = {
    
    
    plugins: [
        new HtmlwebpackPlugin(),
        new webpack.DefinePlugin({
    
    
            "process.env.REACT_ENV": JSON.stringify('production'),
            "GLOBAL_NAME": flag ? JSON.stringify("render") : JSON.stringify("Render")
        })
    ]
}

当我们需要多个全局变量的时候,使用DefinePlugin插件过于繁琐,通常我们把所需的全局变量在不同环境下的值定义在不同的.env文件中,执行构建的时候,把对应的值注入到全局变量中去即可实现不同环境的构建。

Dotenv是一个零依赖模块,可将环境变量从.env文件加载到中process.env,使用模块就可以帮我们自动实现上述的操作。

先看一个官方文档介绍的一个示例,在项目根目录新建.env文件,定义了一些链接数据库相关的数据:

DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3

然后在脚本文件中使用该模块,就可以在process.env中获取上面定义的值:

require('dotenv').config();
console.log({
    
    
    host: process.env.DB_HOST,
    username: process.env.DB_USER,
    password: process.env.DB_PASS
});

Dotenv会自动读取统计目录下.env中相关的内容,实现process.env内容的注入。当然你可以显示声明Dotenv读取环境文件的位置:

require('dotenv').config({
    
     path: './.env' })

Dotenv的预加载可以在运行node命令的时候,隐式地注入环境文件中的内容到process.env,不需要在使用require语句引入Dotenv。其命令如下:

{
    
    
    "scripts": {
    
    
        "dev": "node ./scripts/dev.js",
        "build:gamma": "node -r dotenv/config ./scripts/build.js dotenv_config_path=.gamma.env"
    }
}

其中-r dotenv/config后面指明需要dotenv处理的脚本文件路径,dotenv_config_path=yourpath,指明环境变量文件所在的位置。在这里运行 npm run build:gamma表示执行gamma测试环境的构建,scripts/build.js脚本文件执行的时候,会读取gamma环境文件中变量内容(环境文件只要保证以.env结尾即可,如这里的.gamma.env)。如果我们还有其他的环境,类似的就有npm run build:uat,npm run build:prod等不同环境的构建命令,其对应的dotenv预加载配置也有所不同,这样子即可定义和使用全局变量,实现分环境构建。注意,只用使用Dotenv处理过的js文件才能使用这些全局变量,也就是说使用Dotenv添加的变量只是局部全局变量。

关于Dotenv更多使用技巧请前往https://www.npmjs.com/package/dotenv进行查阅。

在本章节,我们介绍了在Webpack中如何定义,获取和使用相关的环境变量,同时也介绍了如何获取命令行参数。在日常开中可以单独使用一种方式也可以多种方式结合使用,让自己的项目配置充满活力。

本章节提供案例源码下载:https://gitee.com/mvc_ydb/webpack/blob/master/envVariable.zip

Guess you like

Origin blog.csdn.net/sinat_41212418/article/details/121915239
29