让Angular路由与Express路由配合工作

15

我在使用Express设置Angular路由时遇到了问题。

我尝试像这里一样做:Express 4、NodeJS、AngularJS路由,但是没有成功。静态的index.html会随着url的改变每次都被访问,但是Angular无法捕获部分内容。

我的Express代码如下:

var express = require("express");
var app = express();
app.use(express.static(__dirname + '/app'));
app.use("*",function(req,res){
    res.sendFile(path.join(__dirname,"app/index.html"));
});
app.listen(1337, function(){
    console.log("Server is listening on port 1337");
});

在我的Angular应用程序中,我有以下内容:

var app = angular.module("myapp",["ngRoute","appControllers"]);

    app.config(["$routeProvider","$locationProvider",function($routeProvider,$locationProvider){
            $locationProvider.html5Mode(true);
            $routeProvider
                    .when("/list",{
                        templateUrl: "/partials/users.html",
                        controller: "userListCntr"
            })
                    .when("/edit", {
                        templateUrl: "/partials/edit.html",
                        controller: "userEditCntr"
            })
                    .when("/register", {
                        templateUrl: "/partials/register.html",
                        controller: "registerCntr"
            })
                    .when("/login", {
                        templateUrl: "/partials/login.html",
                        controller: "registerCntr"
            });

    }]);

我在浏览器控制台中没有任何错误。HTML检查器显示:<!-- ngView: -->,因此指令已经部分初始化。

依赖列表如下:

dependencies": {
    "angular": "1.3.x",
    "angular-mocks": "1.3.x",
    "jquery": "1.10.2",
    "bootstrap": "~3.1.1",
    "angular-route": "1.3.x",
    "angular-resource": "1.3.x",
    "angular-animate": "1.3.x"
  }

这是我的文件结构:

--app (angular app)
   --components
   --js
   --css
   --img
   --assets
   --partials
   --index.html
--node-modules
--server.js (here express settigs are)

我已经针对所有静态资源做出以下更改,但仍然无法正常工作:

app.use(express.static(__dirname+ "/app"));
app.use('/js', express.static(__dirname + '/app/js'));
app.use('/dist', express.static(__dirname + '/../dist'));
app.use('/css', express.static(__dirname + '/app/css'));
app.use('/assets', express.static(__dirname + '/app/assets'));
app.use('/components', express.static(__dirname + '/app/components'));
app.use('/img', express.static(__dirname + '/app/img'));
app.use('/partials', express.static(__dirname + '/app/partials'));

app.all('/*', function(req, res, next) {
    // Just send the index.html for other files to support HTML5Mode
    res.sendFile('/app/index.html', { root: __dirname });
});

请帮忙,因为我找不到解决方案。谢谢!


所以,部分页面没有被渲染?你确定它们正在被加载吗? - João Vilaça
不,它们没有被加载。我的控制台中没有针对部分页面的GET请求。 - kirgol
我无法理解你的意思?我在使用express.static()时做错了什么吗? - kirgol
你把模板(用户、编辑、注册、登录)保存在哪里? - chris
请查看我的问题中的文件结构,其中包含在应用程序目录的partials文件夹中。 - kirgol
显示剩余6条评论
5个回答

9
当你在express.use()中不传递路径时,它默认为/。你设置的*规则可能是多余的或者甚至无法起作用。
另外,由于你使用了html5mode,所以你需要明确区分路由和资源,以免Express尝试为所有请求提供你的index.html文件。
可以参考Angular UI-Router中的示例进行尝试。
var express = require('express');
var app = express();

app.use('/js', express.static(__dirname + '/js'));
app.use('/dist', express.static(__dirname + '/../dist'));
app.use('/css', express.static(__dirname + '/css'));
app.use('/partials', express.static(__dirname + '/partials'));

app.all('/*', function(req, res, next) {
    // Just send the index.html for other files to support HTML5Mode
    res.sendFile('index.html', { root: __dirname });
});

app.listen(3006); //the port you want to use

谢谢,但那并没有起作用。仍然无法获取请求和渲染部分内容。我的Angular应用程序在/app文件夹中,所以我将您的答案更改为:app.use(express.static(__dirname+ "/app")); app.use('/js', express.static(__dirname + '/app/js')); app.use('/dist', express.static(__dirname + '/../dist')); app.use('/css', express.static(__dirname + '/app/css')); app.use('/partials', express.static(__dirname + '/app/partials')); - kirgol
抱歉,请查看我的文件结构(我忘记给它添加代码标签了)。 - kirgol
我好久没用Express了。我看到他们在第4版中改变了API,而UI-Router的示例使用第3版语法。我猜你在用第4版? - joshuahiggins
是的,我在4上。我需要改变语法吗?问题是我只学了4天的Express,信息量太大了。请帮忙。 - kirgol
Joshua,非常感谢你的努力。我刚刚发现我应该在我的index.html的头部添加<base href="/" />。在这里找到:https://dev59.com/UWMl5IYBdhLWcg3wr4nn. 然后它奇迹般地起作用了。Angular最后抓住了这个部分! - kirgol
显示剩余5条评论

2

1
在你的代码中,包含文件和脚本的<link><script>标签之前,有<base href="/" />是非常重要的。 - jigarzon

1

我只想补充一点,添加base href=对我很有帮助。我的应用程序在express中以静态方式提供服务,直接浏览我的angular应用程序中的路由会导致大量错误:

拒绝执行脚本,因为其MIME类型('text / html')不可执行,并启用了严格的MIME类型检查。

但是添加base href修复了这个问题,现在我可以直接浏览我的angular路由。


0

我也遇到了一个类似的情况,想通过express路由来使用angular组件,以下是我解决路由问题的方法:

我的Nodejs项目设置:

  • 为生产构建Angular项目,并放置在public文件夹中。
  • 创建一个app.js文件用于express服务器,其中包含以下内容:

    var express = require('express'); var app = require('express')(); const port = 8090; app.use(express.static('public')); app.listen(port,()=>{console.log("App working at port : http://localhost:"+port)});

这样运行后只加载了根组件,我需要手动通过routerLink路由到不同的页面。如果我直接使用URL提供子组件,则会出现Cannot GET/{URL}错误。

修复方法:

  • 我添加了express-http-proxy包并导入为
  • var proxy = require('express-http-proxy');
  • 然后在app.use(express.static('public'));之后添加了以下行:
  • app.use('/*',proxy('http://localhost:'+port+'/*'));

这解决了我的问题。显然有一个更标准的解决方法请参考链接


0
虽然@kirgol提出的使用base href=的解决方案很好,但还有一种替代方案可能会吸引寻找简单路由服务的人。在这个解决方案中,我们不使用ExpressJS路由。
只需使用以下代码:
app.use(express.static(__dirname + '/app'));

用这个代替

app.all('/*', function(req, res, next) {
    // Just send the index.html for other files to support HTML5Mode
    res.sendFile('index.html', { root: __dirname });
});

这样,expressJS 将自动提供静态位置上存在的 index.html,并自动处理路由。它的行为就像一个简单的 http 服务器。一旦你使用 app.all / app.get 处理路由 - 你将不得不设置 base href 来告诉 $locationProvider 它可以匹配路由的位置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接