如何在webpack中添加编译时全局变量?

时间:2017-10-30 14:20:47

标签: javascript webpack

我有一个动态可配置的webpack设置,带有一些自定义加载器。这些加载器中的每一个都需要一个配置对象,该对象在编译时是动态已知的,因此无法在加载器的options中对其进行硬编码。装载程序如何访问此对象?是否有一种“规范”方式在webpack中拥有编译时全局?

基本上,我的设置允许多个动态构建时配置,它看起来像这样:

// webpack.config.js

let defaults = {
   ....
    module: {
        loaders: [
            {
                test: '.some.special.stuff',
                loader: 'my-own-loader',
            }
}

module.exports = function main() {
    let BUILD_CONFIG = require(process.env.BUILD_CONFIG);  
    ....
    return defaults;
}

所以webpack应该被称为BUILD_CONFIG=some-config.js webpack。请注意,some-config.js包含许多非webpack内容,因此我不能仅从main返回它或将其与defaults合并

现在,我在my-own-loader中有my-own-loader.js

// my-own-loader.js

module.exports = function main(content) {
  ...

我的问题是如何从加载程序BUILD_CONFIG中的webpack main访问main变量。

1 个答案:

答案 0 :(得分:2)

我想我明白你要做什么,并有一个详细介绍这个过程的示例项目。

首先,我将通过我的平台支持的任何机制设置名为TEST_VAR的环境变量。我在macOS上,所以那是export TEST_VAR=fizzbuzz。我的 loader.js 能够通过节点约定使用该环境变量:process.env.TEST_VAR

请记住,您的webpack.config.js仍然是节点运行的JavaScript文件。您可以使用节点支持的所有内置函数,包括process.env

考虑以下文件和结构:

结构

webpack-test
|- package.json
|- webpack.config.js
|- index.html
|- /dist
  |- bundle.js
|- /loaders
  | obj-loader.js
|- /res
  |- /obj
    |- dummy.obj
|- /src
  |- index.js

的package.json

{
  "name": "webpack-test",
  "version": "0.0.1",
  "main": "index.js",
  "dependencies": {
    "webpack": "^3.8.1"
  },
  "devDependencies": {
    "http-server": "^0.10.0",
    "loader-utils": "^1.1.0",
  },
  "scripts": {
    "start": "http-server .",
    "build": "webpack",
  },
}

webpack.config.js

const path = require("path");

module.exports = {
    entry: "./src/index.js",
    output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "dist")
    },
    resolveLoader: {
        modules: [
            path.resolve(__dirname, "loaders")
        ]
    },
    module: {
        rules: [
            {
                test: /\.obj$/,
                use: {
                    loader: "obj-loader",
                    options: {
                        dummyText: "lorem ipsum"
                    }
                }
            }
        ]
    }
};

/loaders/obj-loader.js

const loaderUtils = require("loader-utils"),
    schemaUtils = require("schema-utils");

function loader(source) {
    const options = loaderUtils.getOptions(this);
    console.log(options);

    let tmp = process.env.TEST_VAR;
    if (tmp === undefined) {
        console.warn("TEST_VAR is not defined");
    }
    return `export default function(){return "TEST_VAR: ${tmp} || ${source} || ${options.dummyText}";}`;
}

module.exports = loader;

/res/obj/dummy.obj

Hello

/src/index.js

import dummy from "../res/obj/dummy.obj";

(function () {
    "use strict";

    function main() {
        document.querySelector("p").innerHTML = dummy();
    }
    document.addEventListener("DOMContentLoaded", main);
}());

的index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Webpack Test</title>
    <script src="dist/bundle.js"></script>
</head>
<bod>
    <main>
        <h1>Webpack Test</h1>
        <p>Lorem Ipsum</p>
    </main>
</bod>

</html>

每当我构建并运行此网页时,我都会得到以下内容:

<main>
    <h1>Webpack Test</h1>
    <p>TEST_VAR: fizzbuzz || Hello || lorem ipsum</p>
</main>

从环境变量中添加“fizzbuzz”,“Hello”源是/res/obj/dummy.obj,“lorem ipsum”是我为{{dummyText选项指定的文本1}}。但是,它可能很容易来自我设置的环境变量。

基于修改的其他更新

考虑到你的编辑,这个怎么样;而不是在obj-loader中设置规则,而是在导出的函数中设置它以获得范围访问权限。然后根据新规则语法添加加载程序规则:module.loaders is now module.rules。这样,您就可以在自定义加载器中访问defaults,从而可以访问options

较新的webpack.config.js

BUILD_CONFIG

我 - 拥有 - loader.js

// Hypothetically you run:
// export BUILD_CONFIG=some-config.js
// Which sets:
// process.env.BUILD_CONFIG = "some-config.js";

// New Webpack loader/rules syntax
// https://webpack.js.org/guides/migrating/#module-loaders-is-now-module-rules
let defaults = {
    module: {
        rules: [
            /*
             *Set this later in exported function
            {
                test: ".some.special.stuff",
                use: {
                    loader: "my-own-loader",
                    options: {
                        some: "options"
                    }
                }
            }
             */
        ]
    }
};

module.exports = function (content) {
    let BUILD_CONFIG = require(process.env.BUILD_CONFIG);    
    // Other code

    let dd = defaults;
    defaults.module.rules.push({
        test: ".some.special.stuff",
        use: {
            loader: "my-own-loader",
            options: {
                stuffFromEnvConfig: BUILD_CONFIG
            }
        }
    });

    return dd;
};