Подтвердить что ты не робот

Angular маршрутизация в HTML5mode с Node.js

Я знаю, что есть другие ответы на это, но они, похоже, имеют оговорки.

Это вызывает перенаправление, что может быть фатальным для моего внешнего приложения, которое использует Mixpanel, а двойная загрузка Mixpanel будет максимальным размером стека вызовов Превышена ошибка в браузере.

Этот использует sendFile, который я лично не могу заставить работать. Пытаясь диагностировать это, мне просто рекомендуется использовать express.static().

В настоящее время мой код выглядит следующим образом:

home.js - Некоторые маршруты, последний из которых должен быть интерфейсом.

var indexPath = path.resolve( __dirname, '../' + process.env.PUBLIC_FOLDER )

router.get( '/:user/:stream/:slug', function( req, res, next ) {

    if ( req.headers['user-agent'].indexOf( 'facebook' ) != -1 ) {
        // stuff to handle the Facebook crawler
    } else return next()
})

router.get( '/*', function( req, res ) {
    express.static( indexPath )
})

server.js - настройка node/express

app = express();

app 
    .use( morgan( 'dev' ) )
    .use(bodyParser.urlencoded( { limit: '50mb', extended: true } ) )
    .use( bodyParser.json( { limit: '50mb' } ) )
    .use( '/api', require('./routes/usersRoute.js') )
    .use( '/', require( './routes/home' ) )
    .on( 'error', function( error ){
       console.log( "Error: " + hostNames[i] + "\n" + error.message )
       console.log( error.stack )
    })

http
    .createServer( app ).listen( process.env.PORT )
    .on( 'error', function( error ){
       console.log( "Error: " + hostNames[i] + "\n" + error.message )
       console.log( error.stack )
    })

Дополнительная информация

Причина, по которой я пытаюсь использовать express.static(), заключается в том, что, когда я использую res.sendfile(), я получаю проблему как этот, где консоль говорит Unexpected token '<'. К сожалению, ответ не указывает точное исправление, и ни один из участников опроса не говорит, что исправил проблему, но не дал ответа.

В моей пробной версии и ошибке я добавил еще несколько выражений, например

.use( '/app/app.js', express.static( indexPath + '/app/app.js' ) )
.use( '/app/views', express.static( indexPath + '/app/views' ) )
.use( '/app/controllers', express.static( indexPath + '/app/views' ) )
.use( '/app/directives', express.static( indexPath + '/app/views' ) )
.use( '/app/vendor', express.static( indexPath + '/app/vendor' ) )
.use( '/js', express.static( indexPath + '/js' ) )
.use( '/css', express.static( indexPath + '/css' ) )
.use( '/fonts', express.static( indexPath + '/fonts' ) )
.use( '/images', express.static( indexPath + '/images' ) )
.use( '/api', require('./routes/usersRoute.js') )
.all( '/*', require( './routes/home' ) )

И в моих home.js файлах маршрутов добавлено это

router.get( '/*', function ( req, res ) {
    res.status( 200 ).set( { 'content-type': 'text/html; charset=utf-8' } )
    .sendfile( indexPath + '/index.html' )
})

И в браузере я вижу, что все мои файлы загружаются, но с ошибкой < выше. Я вижу, что этот маршрут /*/ вызывается сотни раз, когда я делаю обновление, поэтому я думаю, что конфигурации .use( '...', ... ) игнорируются.


Вот еще один пример, запрошенный Йонасом ниже.

var indexPath = path.resolve( __dirname, process.env.PUBLIC_FOLDER )

mongoose.connect( process.env.MONGOLAB_URI )

app = express();

app 
    .use( morgan( 'dev' ) )
    .use(bodyParser.urlencoded( { limit: '50mb', extended: true } ) )
    .use( bodyParser.json( { limit: '50mb' } ) )
    .use( '/api', require('./routes/usersRoute.js') )
    .use( '/', require( './routes/home.js' ) )
    .use( express.static( indexPath ) )
    .on( 'error', function( error ){
       console.log( "Error: " + hostNames[i] + "\n" + error.message )
       console.log( error.stack )
    })

Я также сделал то же самое без строки .use( '/', require( './routes/home.js' ) ), чтобы попытаться сузить любую проблему, но это тот же результат. Страница будет загружаться, если у меня есть # в URL-адресе, но браузер удалит # (пока это так хорошо). Но если я нажму обновить или поместил URL вручную, sans-hashbang, он даст ошибку, например, Cannot GET /home/splash, где /home/splash - это тот путь, к которому я собираюсь.

4b9b3361

Ответ 1

Возможно, вы используете неправильное промежуточное программное обеспечение. Глядя на документация, я скажу, например, что следующий код

.use( '/images', express.static( indexPath + '/images' ) )

Служит для доступа к любому файлу в папке indexPath + '/images' с такими URL-адресами:

http://localhost:3000/images/kitten.jpg
http://localhost:3000/images/logo.png
http://localhost:3000/images/whatever.jpg

Это то, что вы ожидаете от этого?

Мое предложение состоит в том, чтобы перейти от

.use( '/', require( './routes/home' ) )

к

.use(express.static( indexPath ))

Потому что согласно документации, он будет обслуживать все статические файлы в папке indexPath из корневого пути, иначе. без префикса.

Я думаю, что это все, что я могу помочь с теми данными, которые вы дали до сих пор. Если это не делает трюк, возможно, вы можете поделиться небольшим примером кода, который я могу использовать, чтобы воспроизвести его самостоятельно.

UPDATE

Ok. Я попытался создать простой пример. Я сделал это следующим образом. Моя структура каталогов такова:

|- index.js
|- public/
|---- index.html
|---- test.html
|---- main.js
|---- angular.js
|---- angular-route.js

index.js - сервер node. Обратите внимание на порядок маршрутизации. Я также добавил пример /home/login, чтобы дать понять, как добавить другие маршруты сервера, которые не должны проходить через angular.

var http = require('http');
var express = require('express');
var app = express();

app
    .use(express.static('public'))
    .get('/home/login', function (req, res) {
        console.log('Login request');
        res.status(200).send('Login from server.');
    })
    .all('/*', function ( req, res ) {
        console.log('All');
        res
            .status( 200 )
            .set( { 'content-type': 'text/html; charset=utf-8' } )
            .sendfile('public/index.html' );
    })
    .on( 'error', function( error ){
       console.log( "Error: \n" + error.message );
       console.log( error.stack );
    });

http
    .createServer( app ).listen( 8080 )
    .on( 'error', function( error ){
       console.log( "Error: \n" + error.message );
       console.log( error.stack );
    });

console.log('Serving app on port 8080');

index.html довольно прост.

<!doctype html>
<html>
<head>
    <title>Angular HTML5 express test</title>
    <script type="text/javascript" src="angular.js"></script>
    <script type="text/javascript" src="angular-route.js"></script>
    <script type="text/javascript" src="main.js">
    </script>
</head>
<body ng-app="app">
    <div ng-view></div>
</body>
</html>

main.html просто добавляет некоторый контент. Важная ссылка на /test

<div>
    <h1>This is just a {{val}}</h1>
    <button ng-click="clicked()">Click me!</button>
    <span>You clicked {{counter}} times</span>
    <a href="/test">test me!</a>
</div>

test.html фактически не имеет значения

<div>
    <h4>What a beautiful day to test HTML5</h4>
</div>

main.js выполняет основную работу angular html5

angular.module('app', ['ngRoute'])
    .config(function($locationProvider) {
        $locationProvider
            .html5Mode({
                enabled: true, // set HTML5 mode
                requireBase: false // I removed this to keep it simple, but you can set your own base url
            });
    })
    .config(function($routeProvider) {
        $routeProvider
            .when('/test', {templateUrl: 'test.html', controller: function() {
                console.log('On /test.');
            }})
            .when('/', {templateUrl: 'main.html', controller: 'MyTestCtrl'})
            .otherwise('/');
    })
    .controller('MyTestCtrl', function ($scope) {
        self = $scope;
        self.val = 'TeSt';
        self.counter = 0;
        var self = self;
        self.clicked = function() {
            self.counter++;
        };
    });

Ответ 2

вместо:

router.get( '/*', function( req, res ) {
    express.static( indexPath )
})

do

router.get( '/:anyreq', function( req, res ) {
    express.static( indexPath )
})

просто сохраните его в конце файла маршрутов.

Ответ 3

Кажется, что может возникнуть проблема с вашими запросами AJAX.
Обычно я настраивал свои маршруты следующим образом:

app.use(express.static(path.join(__dirname, "./public"))); app.use("/", require(path.join(__dirname, "./routes")));

и совершать вызовы на передней панели с помощью templateUrl: "/templates/home.html" в директиве

или $http.get("/images").success(...).error(...), используя $http.

В случае templateUrl приложение войдет в общий каталог, затем шаблоны маршрутов и будет обслуживать html файл. В случае $http я указываю маршрут, поэтому приложение проверяет общий каталог, не видит путь к изображениям и поэтому переходит к маршрутизатору. В маршрутизаторе у меня есть router.get("/images", function (req, res, next) { res.sendFile(...); или res.send({(data)}) }), который отправляет файл, который мне нужен, в переднюю часть, где он попадает в обработчик успеха.