我可以从捆绑的 javascript 应用程序中加载文件吗?

Posted

技术标签:

【中文标题】我可以从捆绑的 javascript 应用程序中加载文件吗?【英文标题】:Can I load a file from a bundled javascript application? 【发布时间】:2018-12-11 00:03:44 【问题描述】:

我有一个节点应用程序,它在构建时被捆绑到一个文件中。我想从这个捆绑包中拆分出应用配置参数(它只是一个简单的对象)。

./build 目录变成只有三个文件:index.jsconfig.js 和一个地图文件。

当我cd 进入目录并使用node index.js 启动应用程序时,我收到以下错误:

TypeError: Cannot read property 'logPath' of undefined
    at Module.<anonymous> (/home/*/repo/build/index.js:1:2367)
    at t (/home/*/repo/build/index.js:1:172)
    at /home/*/repo/build/index.js:1:964
    at Object.<anonymous> (/home/*/repo/build/index.js:1:973)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
    at startup (bootstrap_node.js:191:16)
    at bootstrap_node.js:612:3

构建的config.js文件的顶部看起来像

"use strict";
Object.defineProperty(exports, "__esModule",  value: true );
exports.config = 
    logPath: 'logs',
    ....
;

我使用的 webpack 配置看起来是这样的

const path = require('path');
const nodeExternals = require('webpack-node-externals');

function excludeConfig(context, request, callback) 
    /config/.test(request)
        ? callback(null, 'require("./config.js")', + request)
        : callback();


module.exports = 
    entry: 
        index: path.resolve(__dirname, './src/server/index.js')
    ,
    module: 
        rules: [
            
                test: /\.ts$/,
                loader: 'awesome-typescript-loader',
                exclude: ['node_modules']
            , 
                test: /\.js$/,
                loader: 'source-map-loader',
                enforce: 'pre'
            
        ]
    ,
    resolve: 
        extensions: ['.ts', '.tsx', '.js', '.jsx'],
        modules: [path.resolve(__dirname, 'node_modules')]
    ,
    devtool: 'source-map',
    output: 
        filename: 'index.js',
        path: path.join(__dirname, '/build')
    ,
    mode: 'production',
    target: 'node',
    externals: [
        nodeExternals(),
        excludeConfig
    ],
;

gulp 正在使用以下策略构建我的配置文件

const ts = require('gulp-typescript');
const tsProject = ts.createProject('tsconfig.json');
gulp.task('add-config', function () 
    return gulp
        .src('src/*config.ts')
        .pipe(tsProject())
        .pipe(gulp.dest('build'));
);

tsconfig.json 文件如下所示:


    "compilerOptions": 
        "outDir": "./build",
        "allowJs": true,
        "checkJs": false,
        "module": "commonjs",
        "target": "es5",
        "moduleResolution": "node",
        "lib": ["es2015", "dom"]
    

我的直觉是,在构建之后,配置文件没有提供捆绑包所期望的内容。

捆绑包确实包含以下行:

function (e, r)  e.exports = require("./config.js") 

关于如何让包加载config.js 文件的任何想法?

【问题讨论】:

【参考方案1】:

似乎经过大量静态分析,并且对导入模块的不同方式缺乏全面了解,出于某种原因,捆绑包将我的配置文件定义为和谐导入并尝试从文件中检索default (在我的情况下我没有)。

有两个可用的修复程序(都运行良好):

通过在导入周围使用方括号将导入样式更改为不使用默认值(我不知道为什么我更喜欢这个)
import  config  from './../../config';
更改导出样式,采用默认路由
export default <Config>
    logPath: 'logs',
    ...
;

老实说,当这个项目还没有开始迁移到 TypeScript 之前,我不知道为什么这会奏效。我知道所有与 babel 相关的东西在我开始之前都被删除了,所以我无法理解它。

Webpack 内部结构

模块加载器如下所示:

(function(module, exports) 
    module.exports = require("./config.js");
)

然后将其传递给另一个模块并按如下方式加载:

/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./../../config */ "./../config");
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_config__WEBPACK_IMPORTED_MODULE_1__);
const PATH = _config__WEBPACK_IMPORTED_MODULE_1___default.a.logPath.replace(/\/*$/, '');

注意_config__WEBPACK_IMPORTED_MODULE_1__ 已经拥有我的配置对象的内容。然而,webpack 将它发送到一个函数 n 中,该函数将导入封装到成员 a 上的一个 getter 函数中。如果模块被标记为esModule,则此封装解析为使用default

__webpack_require__.n = function(module) 
    var getter = module && module.__esModule ?
        function getDefault()  return module['default'];  :
        function getModuleExports()  return module; ;
    __webpack_require__.d(getter, 'a', getter);
    return getter;
;

【讨论】:

以上是关于我可以从捆绑的 javascript 应用程序中加载文件吗?的主要内容,如果未能解决你的问题,请参考以下文章

将数据从 html 引导到 webpack 捆绑的 javascript

无法在捆绑包中加载 Nib

无法在捆绑包中加载 NIB。可可豆项目

从 HTML 文件访问捆绑的 javascript(使用 webpack)中的函数

公开通过 webpack 捆绑的 javascript 全局变量

OSX 部署:第 3 方库在 /Applications 中加载插件(自定义)而不是捆绑