AngularJS和Express路由404

5

我有一个AngularJS应用程序:

angular.module('app', ['ngRoute', 'app.controllers'])
.config(['$routeProvider', function($routeProvider){
    $routeProvider
        .when('/', {
            controller: 'HomeController',
            templateUrl: 'views/home.html'
        })
        .when('/garage', {
            controller: 'GarageController',
            templateUrl: 'views/vehicle.html'
        })
        .otherwise({
            redirectTo: '/'
        });
}])
.config(['$locationProvider', function($locationProvider) {
    $locationProvider.html5Mode(true);
}]);

Node.js是我的后端,它的唯一目的是提供REST API(尚未实现)。Express配置如下:

app.use(express.static(path.join(__dirname, 'public')));

app.get('*', function(req, res) {
   res.sendFile(__dirname + '/public/index.html');
});

问题是,每当我在地址栏中输入一些无效的 URL,例如 http://localhost:3000/abc,请求就会到达服务器。我认为,应该由 AngularJS 路由处理并重定向到默认的 '/' 页面。为什么没有发生呢?
当这种情况发生时,整个应用程序都会再次下载,包括所有的索引和资源文件。我想告诉 AngularJS - 每当有人输入无效的路由时,只需路由到默认路由即可。而且这应该只替换 ng-view,而不是再次下载整个 index.html。这可能吗?
谢谢

这里没有人能帮我吗? - pshemu
我有同样的问题,你最终解决了问题吗 :) - vrghost
很遗憾,不是的 :( - pshemu
我在想这是否是因为你需要有两个路由?也就是说,你需要让你的Angular路由只接收自己的调用,否则你可能会在进行API调用时遇到问题(例如,假设你有www.../api/getdata和www.../api/savedata,你需要一种方式让Angular知道它应该响应/、/garage以及任何其他组合,但不包括/api/....)。不过这可能是错误的。 - vrghost
我的最大问题是,否则在Angular路由中似乎根本无法工作,而是会向服务器发出请求。 - pshemu
2个回答

0

不确定这是否有帮助,但这个路由非常有效。(app.js)

var routes = require('./routes/index');
var users = require('./routes/users');
var api = require('./routes/api')
var partials = require('./routes/partials')

然后在另一端,使用以下代码来启动和运行Angular路由:

    var BabyPadz = angular.module('BabyPadz', ["ngResource", "ngRoute"]).
    config(['$routeProvider', '$locationProvider',
        function ($routeProvider, $locationProvider) {
            $locationProvider.html5Mode(true);
            $routeProvider
                .when('/', {
                    templateUrl: 'partials/index',
                    controller: 'IndexController'
                })
                .when('/about', {
                    templateUrl: '/partials/about',
                    controller: 'AboutController'
                })
                .when('/contactus', {
                    templateUrl: "partials/contactus",
                    controller: 'ContactController'
                })
                .when('/boompad', {
                    templateUrl: "partials/boompad",
                    controller: "BoomController"
                })

                // route for the about page

                .otherwise({redirectTo: "/test"});
        }
    ]
);

我意识到我也使用了ngResource,知道一两年前有些事情发生了变化,涉及到Angular的拆分(因此Route等是一个单独的模块)。不确定是否如此。
有时仍然会收到404错误,但认为这是服务器端允许Angular接管路由的问题,但我还没有完全得到答案,即服务器/ Angular如何协同工作或哪个优先级更高。

当您在浏览器中键入/aaaa时,将被重定向到/test? - pshemu
是的,如果我输入任何内容(包括/aaaa),它都可以很好地重定向。 - vrghost
这很奇怪,因为我的配置看起来几乎一样,但当请求/aaaa时,请求被发送到服务器并且浏览器下载index.html。你使用的是什么浏览器? - pshemu
我使用Chrome。如果问题类似于我遇到的问题,那么问题可能出在您的服务器路由上。其他路由是否正常工作? - vrghost

0

我曾经遇到和你一样的问题,这里有两个可能的解决方案!

//////////////////////////////

解决方案1:列出您想/不想“提供”的目录

//////////////////////////////

如何:

假设您的目录结构如下:

-app/
---controllers/
---directives/
---etc.
-public/
---img/
---css/
---index.html
---etc.
-views/
---home.html
---vehicle.html
---etc.
-app.js (run with 'node app.js')

其中这3个文件夹(app、public、views)的规则不同,您需要决定哪些要进行serve,哪些要进行render

  • app/
    • serve: 如果您的网站执行 GET /app/controller.js 命令,则需要向他们提供该文件。
  • public/
    • serve: 如果您的网站执行 GET /public/img/logo.jpg 命令,则需要向他们提供该文件。
  • views/
    • render: 如果您的网站执行 GET views/home 命令,则需要从您的 angular.js 路由中渲染视图。

现在,在您的 node/express js 文件中,找到或添加以下内容:

//This tells node that these folders are for STATIC SERVING files (meaning literal files). 
//And Yes! You can use multiple to indicate multiple directories.
app.use(express.static(path.join(__dirname, 'app')));
app.use(express.static(path.join(__dirname, 'public')));

更多信息:

app.use(express.static(__dirname + '/client/views')); 表示您正在从 /client/views 目录下提供字面文件,但不包括该目录之外的任何内容。请参见 视图文件夹中的angularjs index.html

扩展示例:

这将是您可能的配置:

//app.js

var express = require('express'),
  bodyParser = require('body-parser'),
  methodOverride = require('method-override'),
  errorHandler = require('error-handler'),
  morgan = require('morgan'),
  routes = require('./routes/index'), //My special routes file
  http = require('http'),
  path = require('path');

var app = module.exports = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(morgan('dev'));
app.use(bodyParser());
app.use(methodOverride());
app.use(express.static(path.join(__dirname, 'app')));
app.use(express.static(path.join(__dirname, 'public')));

// serve index and view partials
app.get('/', routes.index);

//Partials
app.get('/partials/:name', routes.partials);

// redirect all others to the index
// BUT the static files listed above still get served statically
app.get('*', routes.index);

http.createServer(app).listen(app.get('port'), function () {
  console.log('Express server listening on port ' + app.get('port'));
});

那么这将是你的路由文件:

exports.index = function(req, res){
  res.render('index');
};

exports.partials = function (req, res) {
  var name = req.params.name;
  res.render('partials/' + name);
};

//////////////////////////////

解决方案 #2:先检查文件是否存在

//////////////////////////////

如何:

保持现有的所有内容不变,但是在尝试“res.sendFile”之前先检查它是否存在。例如:

exports.all = function (req, res) {
    var name = req.params[0];
    fs.exists(path+'/'+name, function(exists){
        if(exists)
        {
                //console.log("file exists");
                res.sendFile(path+'/'+name);
        }else{
                //console.log("file does not exist");
                //redirects to index
                res.render('index');
        }
    });
};

扩展示例:

这将是您可能的配置:

//app.js

var express = require('express'),
  bodyParser = require('body-parser'),
  methodOverride = require('method-override'),
  errorHandler = require('error-handler'),
  morgan = require('morgan'),
  routes = require('./routes/index'), //My special routes file
  http = require('http'),
  path = require('path');

var app = module.exports = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(morgan('dev'));
app.use(bodyParser());
app.use(methodOverride());
app.use(express.static(path.join(__dirname, '')));

// serve index and view partials
app.get('/', routes.index);

//Partials
app.get('/partials/:name', routes.partials);

// redirect all others
app.get('*', routes.all);

http.createServer(app).listen(app.get('port'), function () {
  console.log('Express server listening on port ' + app.get('port'));
});

这是你的路由文件:

var fs = require('fs');
var path = require('path');

exports.index = function(req, res){
  res.render('index');
};

exports.partials = function (req, res) {
  var name = req.params.name;
  res.render('partials/' + name);
};

exports.all = function (req, res) {
    var name = req.params[0];
    fs.exists(path+'/'+name, function(exists){
        if(exists)
        {
                //console.log("file exists");
                res.sendFile(path+'/'+name);
        }else{
                //console.log("file does not exist");
                //redirects to index
                res.render('index');
        }
    });
};

//////////////////////////////

希望这能帮到你!


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