0

我正在尝试编写一个自定义 Webpack 加载器,它读取 JavaScript 文件并导出 SASS 变量,类似于js-to-sass-var-loader但具有一些附加功能。

/webpack-loaders/js-to-sass-loader.js

import _ from 'lodash';
import path from 'path';

const importRegex = /@import\s+'([^']+\.js)'\s*;/ig;

/* 
    functions for transforming...
*/

export default function (content) {
    let self = this;

    // search for "@import '*.js';" and replace that text with
    // the transformed output of the specified JavaScript file
    return content.replace(importRegex, (match, relativePath) => {
        if (match) {
            let modulePath = path.join(self.context, relativePath);
            self.addDependency(modulePath);
            let data = require(modulePath).default;
            return transform(data);
        }
    });
}

这个 JavaScript 文件加载一个 .json 配置文件,进行一些处理并吐出一个对象。

/client/sass/sassConfig.js

import config from '../../config.json';

console.log('Generating SASS variables.');
let sass = {
    // some special values here
    };

for (let key of Object.keys(config.style)) {
    sass[key] = config.style[key];
}

sass.debug = (process.env.NODE_ENV || 'production').trim() === 'development';

export default sass;

json 文件包含注释,所以我用另一个简单的加载器将它们剥离。这只是使用json5解析 json 文件,然后将输出字符串化并传递。

/webpack-loaders/remove-json-comments-loader.js

import json5 from 'json5';

export default function (source) {
    return JSON.stringify(json5.parse(source));
}

我的 webpack.config.babel.js 包含 sass 和 json 文件使用这两个加载器的规则。

/webpack.config.babel.js

// ... imports ...

const webpackConfig = {
    entry: {
        app: './client/script.js',
    },

    output: {
        filename: 'script.js',
        path: path.resolve(__dirname, 'public')
    },

    resolveLoader: {
        alias: {
            'js-to-sass-loader': path.resolve(__dirname, 'webpack-loaders/js-to-sass-loader'),
            'remove-json-comments-loader': path.resolve(__dirname, 'webpack-loaders/remove-json-comments-loader')
        }
    },

    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
            },
            {
                test: /\.json$/,
                exclude: /node_modules/,
                loader: 'remove-json-comments-loader',
            },
            {
                test: /\.s[ca]ss$/,
                exclude: /node_modules/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: [
                        { loader: 'css-loader' },
                        { loader: 'sass-loader' },
                        { loader: 'js-to-sass-loader' },
                    ]
                }),
            },
            // ...
        ],
    },

    plugins: [
        // ...
        new ExtractTextPlugin({ filename: 'style.css' }),
        // ...
    ],

    // ...
};

module.exports = webpackConfig;

在我的一些 JavaScript 文件中,我可以import Config from './path/to/config.json'毫无问题。它正确使用remove-json-comments-loader. 但是当我js-to-sass-loader尝试 require时sassConfig.js,Webpack 不使用加载器进行解析config.json。它尝试将其作为常规 json 文件加载,这导致它由于注释而失败。我试过使用import config from '!!remove-json-comments-loader!../../config.json';,但 webpack 说它找不到文件。

我对编写 webpack 加载器非常陌生,所以我确信这很简单。帮助?谢谢!

这是 github 存储库的链接:https ://github.com/dfoverdx/PokeStreamer-Tools/tree/9b4c7315d5dc6b30c5972a0b8678489598311bf0

要重现此问题,请打开/node/client/sass/sassConfig.js并将前四行更改为:

// import json5 from 'json5';
// import fs from 'fs';
// const config = json5.parse(fs.readFileSync('config.json'));
import config from '../../config.json';

也就是说,注释前 3 行并取消注释第 4 行。

/node运行npm run build到产生错误。

4

1 回答 1

0

如前所述,以下是我的观察

  • 您正在尝试创建加载程序
  • 您的加载程序直接使用本require机 nodejs 方法需要文件
  • js-to-sass-loader需要sassConfig.js然后config.json直接需要文件
  • config.json是具有注释的本机文件,因此不能这样要求

所以关键是你正在混合 webpack,这基本上是将东西捆绑到包中,然后需要捆绑的代码。这就是为什么 json 在其余代码中工作而不是在sassConfig.js.

理想情况下,加载程序不应该require处理json文件本身。处理后的json文件应该放在捆绑包中,而不是作为加载程序内部代码的一部分。所以最好只使用你用来加载模块的解决方法config.jsonjson5这确保你的加载器不是在寻找修改过的代码本身

于 2018-03-16T19:18:37.590 回答