简体   繁体   English

使用Node.js在HTML5mode中进行角度路由

[英]Angular routing in HTML5mode with Node.js

I know there are other answers to this but they seem to have caveats. 我知道还有其他答案,但他们似乎有警告。

This one causes a redirect , which can be fatal for my front-end app which uses Mixpanel, and a double-load of Mixpanel will a Maximum Call Stack Size Exceeded error in the browser. 这个导致重定向 ,这对于使用Mixpanel的前端应用程序来说可能是致命的,而混合面板的双重加载将导致浏览器中的最大调用堆栈大小超出错误。

This one uses sendFile which I personally cannot get to work. 这个使用sendFile ,我个人无法上班。 Trying to diagnose that, I'm just advised to use express.static() . 试图诊断,我只是建议使用express.static()

Currently my code looks like this: 目前我的代码如下所示:

home.js - Some routes, the last one intended to be the front-end site. 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 - configuring node/express 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 )
    })

Some more info 更多信息

The reason you can see I'm trying to use express.static() is because when I use res.sendfile() I get a problem like this one where the console says Unexpected token '<' . 您可以看到我正在尝试使用express.static()的原因是因为当我使用res.sendfile()我遇到了一个类似于控制台说出Unexpected token '<' Unfortunately the answer doesn't specify an exact fix and neither does the questioner who says they fixed the problem but don't share an answer. 不幸的是,答案没有指明一个确切的解决方案,提问者也没有说他们解决了问题,但没有分享答案。

In my trial and error I have added some more to express, like this 在我的试验和错误中,我添加了更多来表达,像这样

.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' ) )

And in my home.js routes files added this 在我的home.js路由文件中添加了这个

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

And in the browser I can see all my files are loading, but with the < error above. 在浏览器中,我可以看到我的所有文件都在加载,但上面有<错误。 I see this /*/ route is being called hundreds of times when I do a refresh so I think the .use( '...', ... ) configurations are being ignored. 当我刷新时,我看到这个/*/ route被调用了数百次,所以我认为.use( '...', ... )配置被忽略了。


Here is another example requested by Jonas below. 以下是Jonas要求的另一个例子。

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 )
    })

I have also done the same without the .use( '/', require( './routes/home.js' ) ) line to try narrow down any problem, but it's the same result. 我也做了同样没有.use( '/', require( './routes/home.js' ) )行尝试缩小任何问题,但结果相同。 The page will load if I have the # in the URL, but the browser will remove the # (so far so good). 如果我在URL中有# ,页面将加载,但浏览器将删除# (到目前为止很好)。 But if I press refresh, or put in the URL manually, sans-hashbang, it will give an error like Cannot GET /home/splash , where /home/splash is whatever path I'm going to. 但是如果我按下刷新,或手动输入URL,sans-hashbang,它会给出一个错误,比如Cannot GET /home/splash ,其中/home/splash是我要去的路径。

You might be using the express middleware in the wrong way. 您可能以错误的方式使用快速中间件。 Looking at the documentation tells me for example that the following code 查看文档告诉我例如以下代码

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

Serves any file under the folder indexPath + '/images' with such URLs: 使用以下URL为indexPath + '/images'文件夹下的任何文件提供服务:

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

Is that what you would expect it to do? 这是你期望它做的吗?

My suggestion is to change from 我的建议是改变

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

to

.use(express.static( indexPath ))

Because according to the documentation, it will serve all static files under the indexPath folder from the root path, aka. 因为根据文档,它将从根路径,也称为indexPath文件夹下的所有静态文件。 with no prefix. 没有前缀。

I think that is all I can help with the input you gave so far. 我认为,到目前为止,我可以帮助您完成所有的输入。 If that doesn't do the trick, maybe you can share some small code example that I can use to reproduce it on my own. 如果这不起作用,也许你可以分享一些我可以用来自己重现它的小代码示例。

UPDATE UPDATE

Ok. 好。 I've tried to create a simple example of it. 我试图创建一个简单的例子。 I made it work in the following way. 我通过以下方式使其工作。 My directory structure is like this: 我的目录结构是这样的:

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

index.js is the node server. index.js是节点服务器。 Pay attention to the order of the routing . 注意路由顺序 I also added some /home/login example to make it clear how to add other server routes that should not go through angular. 我还添加了一些/home/login示例,以明确如何添加不应通过角度的其他服务器路由。

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 is pretty simple. 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 just adds some content. main.html只是添加了一些内容。 Important is the link to /test 重要的是到/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 is actually irrelevant test.html实际上是无关紧要的

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

main.js is doing the core angular html5 work main.js正在做核心角色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++;
        };
    });

instead of: 代替:

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

do

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

just keep it at end of routes file. 只需将其保留在路径文件的末尾。

It seems like there might be a problem with your AJAX requests. 您的AJAX请求似乎可能存在问题。
I usually set up my routes like this: 我通常设置这样的路线:

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

and make calls on the front end with templateUrl: "/templates/home.html" in a directive 并在指令中使用templateUrl: "/templates/home.html"在前端进行调用

or $http.get("/images").success(...).error(...) using $http. $http.get("/images").success(...).error(...)使用$ http。

In the templateUrl case the app will go into the public directory, then the path templates and serve the html file. 在templateUrl的情况下,应用程序将进入公共目录,然后是路径模板并提供html文件。 In the $http case I'm specifying a route so the app checks the public directory, doesn't see an images path and so moves on to the router. 在$ http的情况下,我正在指定路由,以便应用程序检查公共目录,看不到图像路径,因此转移到路由器。 In the router I have a router.get("/images", function (req, res, next) { res.sendFile(...); or res.send({(data)}) }) which sends the file I need back to the front end where it is caught in the success handler. 在路由器中我有一个router.get("/images", function (req, res, next) { res.sendFile(...);res.send({(data)}) })发送文件我需要回到成功处理程序中捕获的前端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM