将 AngularJS html5mode 与 nodeJS 和 Express 一起使用
Posted
技术标签:
【中文标题】将 AngularJS html5mode 与 nodeJS 和 Express 一起使用【英文标题】:using AngularJS html5mode with nodeJS and Express 【发布时间】:2013-07-21 23:21:57 【问题描述】:我正在使用带有 Express 的 nodeJS 服务器来为我的 AngularJS 应用程序提供服务。当我使用 angularJS 默认路由(hashbangs)时,这一切都很好,但现在我正在尝试激活 html5 模式。
我正在像这样激活 html5mode:
$locationProvider.html5Mode(true).hashPrefix('!');
这就是我的 nodeJS app.js
文件的样子:
var path = require('path'),
express = require('express'),
app = express(),
routes = require(path.join(__dirname, 'routes'));
app.configure(function()
app.use(express.logger('dev'));
app.use(express.compress());
app.use(express.methodOverride());
app.use(express.bodyParser());
app.use(app.router);
app.all("/*", function(req, res, next)
res.sendfile("index.html", root: __dirname + "/../app" );
);
app.use(express.errorHandler(
dumpExceptions: true,
showStack: true
));
);
但是,现在这会将所有请求作为我的 index.html
文件提供,因此我从 requireJS 收到以下错误:
Uncaught SyntaxError: Unexpected token <
我尝试将以下内容添加到我的 nodeJS app.js
,以便它可以正确地为我的资源提供服务:
app.use("/js", express.static(__dirname + "/../app/js"));
app.use("/img", express.static(__dirname + "/../app/img"));
app.use("/css", express.static(__dirname + "/../app/css"));
app.use("/partials", express.static(__dirname + "/../app/partials"));
但仍然没有运气。
我还尝试将 app.all
语句替换为:
app.use(function(req, res)
// Use res.sendfile, as it streams instead of reading the file into memory.
res.sendfile(__dirname + '/../app/index.html');
);
但这也没有用。我该怎么做才能让 angularJS html5mode 与 nodeJS 和 Express 一起工作?谢谢。
【问题讨论】:
您可能看到了Uncaught SyntaxError: Unexpected token <
,因为未按预期找到路径。不是返回您想要的 javascript(或 CSS 等)文件,而是触发“catch all /*”路由并返回 HTML。
应用没有“配置”方法
Uncaught SyntaxError: Unexpected token <
是由于您的 Angular js 应用程序文件未加载而引起的。检查到您的 js 目录的路由。您可能希望将它们从 /
更改为 /public
或其他比 /
更独特的名称
【参考方案1】:
您的初始修复(为特定前缀声明静态中间件处理程序)应该可以正常工作,但您需要确保在任何其他路由之前声明它们(以及app.router
,尽管您没有不需要显式使用它):
// these need to go first:
app.use("/js", express.static(__dirname + "/../app/js"));
app.use("/img", express.static(__dirname + "/../app/img"));
app.use("/css", express.static(__dirname + "/../app/css"));
app.use("/partials", express.static(__dirname + "/../app/partials"));
// any other routes:
app.all("/*", ...);
另外,您需要确保前缀静态处理程序实际上被声明为正常(正确的路径),否则它们将无法找到任何请求的文件,并且请求将传递到中间件链并最终由catch-all 处理程序(应该很容易通过注释掉 catch-all 处理程序并查看任何 JS/CSS/... 请求是否正常进行测试)。
【讨论】:
没错,如果你使用像 nginx 这样的代理服务器,那么你不妨在代理级别设置依赖路由【参考方案2】:像这样配置 express 4 服务器:
app.use(express.static(__dirname + '/public'));
app.get('/*', function(req, res)
res.sendFile(__dirname + '/public/index.html');
);
和角度类似:
app.config(function($stateProvider, $urlRouterProvider, $locationProvider)
$stateProvider
.state('home',
url: '/',
templateUrl: 'templates/main.html'
)
.state('register',
url: '/register',
templateUrl: 'templates/register.html'
);
$urlRouterProvider.otherwise("/");
$locationProvider.html5Mode(
enabled: true,
requireBase: false
);
);
【讨论】:
【参考方案3】:我正在开发一个 Web 应用程序,在客户端使用 Angularjs 和 Requirejs,在服务器上使用 Nodejs。
这里是一些示例代码,向您展示我是如何设置它的。
请注意,此示例显示的是哈希 url,但您可以通过修改中间件函数和角度配置轻松更改它
中间件函数
isXHR: function (req, res, next)
if (req.xhr || req.get("angular-request") === "ajaxRequest")
next();
else
var url = req.url;
var urls = url.split("/");
var last = _.last(urls);
urls = _.without(urls, last);
url = urls.join("/") + "#/" + last //remove the hash if you want to make it html5mode;
res.redirect(url);
服务器路由配置
//I'm using express-namespace to group my routes
app.namespace("/requirements", function()
//Shared local variable used across the application
var info =
app:
title: "Requirements",
module: "app/requirements" // where the angular application stored
//this is the main url that will user request
Route.get("/", function (req, res)
res.cookie("profileRegisterationSteps", 0);
res.render("app/requirements/index", info);
);
//this is the url angular js will request
Route.get("type", filters.isXHR, function (req, res)
res.render("app/requirements/profile/type", info);
);
)
客户端路由配置
require(['App', 'underscore', 'ngAmd'/*angular amd*/, 'autoload'/*No Sense*/, 'appLoader' /*i used to load my scripts file for the route user requested (not all scripts files only who requested) before template laoded*/, 'appRoute'/*this is a list of routes*/], function (app, _, amd, autoload, loader, routes)
app.config(function ($routeProvider, $locationProvider, $httpProvider)
//remove a clearn URL
$locationProvider.html5Mode(false);
//ku dar header kan si uu server ka u ogaado Request in yahay Ajax
$httpProvider.defaults.headers.common['angular-request'] = "ajaxRequest";
//Route Config
var Route = $routeProvider;
//get all routes objects that defined in routes module
_.each(routes, function (route)
// extend the routes module objects and use its properties
Route.when(route.url, _.extend(route,
//call returning function in loader module and write the promise
resolve: _.extend(loader(route))
));
);
Route.otherwise(
redirectTo: "/"
);
);
//start the application
amd.bootstrap(app);
);
应用程序文件
require.config(
paths:
//pages
type: "Apps/requirements/pages/type"
);
define(['App'], function(app)
return function (options)
return
loader: function ($q, $rootScope)
var defer = $q.defer();
var module = options.name// the name of the route (this name corresponds to the requirejs module name above;
if (!!(module))
if (require.defined(module))
defer.resolve();
else
require([module], function ()
$rootScope.safeApply(function ()
defer.resolve();
)
);
else
defer.resolve();
return defer.promise;
);
路由文件
define(function()
return
name : "type",
url : "/",
templateUrl : "/requirements/type",
view : 'services'
)
【讨论】:
以上是关于将 AngularJS html5mode 与 nodeJS 和 Express 一起使用的主要内容,如果未能解决你的问题,请参考以下文章
使用 HTML5Mode 配置多个 AngularJS2 项目的 Nginx 配置
AngularJS - ui-router - MVC 5 - html5mode