AngularJS 和 Express 路由 404

Posted

技术标签:

【中文标题】AngularJS 和 Express 路由 404【英文标题】:AngularJS and Express routing 404 【发布时间】:2015-01-11 02:27:50 【问题描述】:

我有一个以下 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(尚未实现)。快捷配置如下:

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。这可能吗?

谢谢

【问题讨论】:

这里没人能帮我吗? 我也有同样的问题,你有没有弄清楚是什么问题:) 很遗憾没有:( 我想知道这是不是因为你需要有两个路由? IE。你需要你的角度路由只接听它自己的调用,否则你会遇到问题,例如调用 api (即假设你有 www.../api/getdata 和 www.../api/savedata 你需要一种让 Angular 知道的方法应该回答 /、/garage、任何其他组合,但不是 /api/.... 可能是错误的 我最大的问题是,否则在 Angular 例程中似乎根本不起作用,而是向服务器发出请求 【参考方案1】:

不确定这是否有帮助,但这种路由工作得很好。 (app.js)

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

然后在另一端使用以下代码来运行角度路线:

    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 获取路由的服务器端,但无法完全回答该问题如何路由(服务器/角度)协同工作或什么优先。

【讨论】:

当你在浏览器中输入 /aaaa 时,你会被重定向到 /test? 是的,如果我放任何东西(包括 /aaaa),它会很好地重定向。 这很奇怪,因为我的配置看起来非常相似,但是当请求 /aaaa 请求被发送到服务器并且浏览器下载 index.html 时。你用什么浏览器? 我使用 chrome。如果它与我遇到的问题类似,则问题可能出在您的服务器路由中。其他路线有效吗?【参考方案2】:

我遇到了与您完全相同的问题,并为您提供了 2 种可能的解决方案!

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

解决方案 #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:如果您的网站执行 GET /app/controller.js,您希望它们提供文字文件。 公开/ serve:如果您的网站确实 GET /public/img/logo.jpg,您希望它们提供文字文件。 观看次数/ render:如果您的网站确实 GET views/home,您希望 render 他们从您的 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 in views folder

扩展示例:

这将是您可能的配置:

//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');
        
    );
;

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

希望有帮助!

【讨论】:

以上是关于AngularJS 和 Express 路由 404的主要内容,如果未能解决你的问题,请参考以下文章

请求新页面时如何将 AngularJS 路由与 Express (Node.js) 一起使用?

使用 Express/Passport、AngularJS 和 ensureLoggedIn 的身份验证和路由在“/”url 上不起作用

如何使用 Express、AngularJS、Socket.io 广播和获取通知?

为啥要使用 Express 而不是 AngularJS?

将 AngularJS html5mode 与 nodeJS 和 Express 一起使用

使用角度 js 进行路由