Importing Redux into my ASP.NET MVC Project using RequreJS, TypeScript (Error: Script error for "redux", needed by...)

Importing Redux into my ASP.NET MVC Project using RequreJS, TypeScript (Error: Script error for "redux", needed by...)

我正在尝试获取 Redux 状态库与我的 ASP.NET MVC 应用程序以及 TypeScript 和 RequireJS 一起工作的基本示例。

这是一个非常简单的应用程序,我创建了一个新的 ASP.NET MVC 项目,从中删除了很多内容,所以我只有我的节点模块(Redux、RequireJS)和我创建的脚本想在下面执行 (Question.ts),它符合 Question.js.

Question.ts

require.config({
    baseUrl: "/node_modules/",
    paths: {
        "redux": "redux/dist/redux.js"
    }
});

import { combineReducers, createStore } from "redux";
const ADD_SELECTED_ANSWER = 'ADD_SELECTED_ANSWER';

function addSelectedAnswer(selectedQuestionId: number) {
    return { type: ADD_SELECTED_ANSWER, selectedQuestionId }
}

function selectedAnswers(state = [], action) {
    switch (action.type) {
        case ADD_SELECTED_ANSWER:

            var nextState = state;

            nextState.push(state);

            return nextState;

        default:
            return state;
    }
}

var questionApp = combineReducers({
    SelectedAnswers: selectedAnswers
});

var store = createStore(questionApp);

// Log the initial state
console.log(store.getState());

// Every time the state changes, log it
// Note that subscribe() returns a function for unregistering the listener
let unsubscribe = store.subscribe(() =>
    console.log(store.getState())
);

store.dispatch(addSelectedAnswer(100));

TypeScript 将其编译为以下内容 (Question.js):

define(["require", "exports", "redux"], function (require, exports, redux_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    require.config({
        baseUrl: "./",
        paths: {
            "redux": "/node_modules/redux/dist/redux.js"
        }
    });
    var ADD_SELECTED_ANSWER = 'ADD_SELECTED_ANSWER';
    function addSelectedAnswer(selectedQuestionId) {
        return { type: ADD_SELECTED_ANSWER, selectedQuestionId: selectedQuestionId };
    }
    function selectedAnswers(state, action) {
        if (state === void 0) { state = []; }
        switch (action.type) {
            case ADD_SELECTED_ANSWER:
                var nextState = state;
                nextState.push(state);
                return nextState;
            default:
                return state;
        }
    }
    var questionApp = redux_1.combineReducers({
        SelectedAnswers: selectedAnswers
    });
    var store = redux_1.createStore(questionApp);
    // Log the initial state
    console.log(store.getState());
    // Every time the state changes, log it
    // Note that subscribe() returns a function for unregistering the listener
    var unsubscribe = store.subscribe(function () {
        return console.log(store.getState());
    });
    store.dispatch(addSelectedAnswer(100));
});
//# sourceMappingURL=Question.js.map

我正在导航到 Home 控制器,只是 http://localhost:50830/,以便执行应该导入 Redux 的基本脚本并执行 Redux 方法的基本分派来修改状态。

运行 后,我收到以下错误:

require.js:168 Uncaught Error: Script error for "redux", needed by: Question

无论我提供给 import 或 RequireJS basePathpaths 配置的配置如何,我似乎都无法让 TypeScript 以某种方式进行编译这允许它找到我的 Redux 模块。

观点很简单:

Index.cshtml

@{
    ViewBag.Title = "Home Page";
}

Please execute my Redux!

@section scripts
{
    <script data-main="/Scripts/Question.js" src="~/node_modules/requirejs/require.js"></script>
}

这是解决方案的结构:

如何让 TypeScript 编译我的 Question.ts 文件,以便它可以在 redux.js 中加载?

这里有一个 link 的解决方案文件,如果这有助于有人帮助我解决这个问题:https://s3.amazonaws.com/helpme123123/Redux+Playground.zip

好吧,所以当我第一次看这个的时候,我很难错过明显的东西。我将尝试解释问题所在以及解决方法。

第一个问题是你 main, "Scripts/Question" 是一个模块(模块是任何包含顶级 importexport 语句的文件)依赖于在 redux 上。模块的依赖关系必须在它本身可以执行之前解决。但是这个模块首先包含解决它们所需的 RequireJS 配置。

转译后的Scripts/Question.js

define(["require", "exports", "redux"], function (require, exports, redux_1) {
    "use strict";
    require.config({
        baseUrl: "node_modules/"
    });
    var ADD_SELECTED_ANSWER = 'ADD_SELECTED_ANSWER';
    function addSelectedAnswer(selectedQuestionId) {
        return { type: ADD_SELECTED_ANSWER, selectedQuestionId: selectedQuestionId };
    }
    // etc.
});

这是我们的首要问题。 require.config 只会在 Question.js 加载后被调用。但为了实现这一点,RequireJS 显然需要解析并加载 redux。

为了解决这个问题,我们需要在加载依赖于该配置的任何模块之前配置加载程序 RequireJS。

所以首先,我们将 require.config 调用移动到一个新文件中,比如 Scripts/Main.js,具有以下内容

require.config({
    baseUrl: "/",
    paths: {
        "redux": "node_modules/redux/dist/redux"
    }
});

require(["Scripts/Question"], () => {
    console.log("bootstrapped");
});

有关此文件的一些注意事项是

  1. 它将 baseUrl 设置为 "/",即高于 Scripts node_modules。这很重要,因为我们需要从两个位置加载代码。

  2. 它显式映射 redux。像 RequireJS 和 SystemJS 这样的加载器是面向浏览器的。他们不假定或依赖服务器端 JavaScript 约定,例如 "deps are in a folder called node modules and have entry points specified in package.json"(它们是明确的,我喜欢那样)

  3. 配置加载程序后,它会使用实际的主要入口模块调用它。 IIRC 有一个更优雅的方法来做到这一点,但我现在不记得了。

现在我们只需要更改 index.cshtml 以加载 Scripts/Main.js 而不是 Scripts/Question.js

<script data-main="/Scripts/Main.js" src="~/node_modules/requirejs/require.js"></script>

并从 Scripts/Question.js

中删除 require.config 调用