Используя AngularJS html5mode с nodeJS и Express
Я использую nodeJS-сервер с Express для обслуживания моего приложения 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? Спасибо.
Ответы
Ответ 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/...).
Ответ 2
Настройте сервер Express 4 как:
app.use(express.static(__dirname + '/public'));
app.get('/*', function(req, res){
res.sendFile(__dirname + '/public/index.html');
});
и angular как:
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
Я работаю над веб-приложением, использующим Angularjs и Requirejs на клиенте, с Nodejs на сервере.
Вот пример кода, который покажет вам, как я его настроил.
Обратите внимание, что в этом примере показан хэш-код, но вы можете легко изменить его, изменив функцию промежуточного программного обеспечения и angular конфигурацию
Функция промежуточного программного обеспечения
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'
}
}
})