简体   繁体   English

处理MEAN堆栈应用程序地址而不使用片段“#”

[英]Handle the MEAN-stack application address without fragment '#'

Edit 1: Here is a mini code I made that reproduces the error. 编辑1:这是我制作的迷你代码 ,可以重现错误。 Please follow README.md to install. 请按照README.md进行安装。

Edit 2: Finally, I found one solution. 编辑2:最后,我找到了一个解决方案。 Besides $locationProvider.html5Mode(true); 除了$locationProvider.html5Mode(true); ( $locationProvider.hashPrefix('') is NOT necessary for me) and <base href="/" /> , I need to add the follows in routes/index.js , rather than app.js . $locationProvider.hashPrefix('')对我来说不是必需的)和<base href="/" /> ,我需要在routes/index.js而不是app.js添加以下内容。 Then, we do NOT need to add anything more to app.js or nginx or apache like this thread mentions. 然后,我们不需要像app.js或nginx或apache那样添加更多内容,就像这个帖子提到的那样。

var express = require('express');
var router = express.Router();
var path = require('path');
... ...
router.get('*', function(req, res) {
    res.sendfile('./views/index.html'); // load our public/index.html sendFile
    // res.sendFile('index.html', { root: path.join(__dirname, 'views') }); // does not work
});

One problem is, in the server console, it gives express deprecated res.sendfile: Use res.sendFile instead routes/index.js:461:9 . 一个问题是, 在服务器控制台中,它提供了express deprecated res.sendfile: Use res.sendFile instead routes/index.js:461:9 But res.sendFile('index.html', { root: path.join(__dirname, 'views') }); 但是res.sendFile('index.html', { root: path.join(__dirname, 'views') }); can not help, it returns 404 error. 无法帮助,它返回404错误。

My express version is ~4.14.0 ... does anyone know how to fix that? 我的快递版本是~4.14.0 ...有谁知道如何解决这个问题?

OP: OP:

I develop in Mac with Apache a MEAN-stack application that can be requested by https://localhost:3000/#/home . 我在Mac上用Apache开发了一个MEAN-stack应用程序,可以通过https://localhost:3000/#/home请求。 In production with an NGINX server, the application can be requested by https://www.myapp.io/#/home . 在使用NGINX服务器进行生产时,可以通过https://www.myapp.io/#/home请求该应用程序。 The fragment-identifier # is needed in all cases because of angular ui-router . 由于angular ui-router ,在所有情况下都需要片段标识符#

So I wanted to make pretty url without # (eg, https://www.myapp.io/home , https://localhost:3000/home ) work. 所以我想在不做出漂亮的URL # (例如, https://www.myapp.io/homehttps://localhost:3000/home )工作。 I have done the following: 我做了以下事情:

  1. added $locationProvider.html5Mode(true); $locationProvider.hashPrefix('') 添加了$locationProvider.html5Mode(true); $locationProvider.hashPrefix('') $locationProvider.html5Mode(true); $locationProvider.hashPrefix('') in app.config(['$stateProvider'... . app.config(['$stateProvider'... $locationProvider.html5Mode(true); $locationProvider.hashPrefix('') app.config(['$stateProvider'...

  2. added <base href="/" /> in index.html index.html添加了<base href="/" />

As a result, https://localhost:3000/#/home changes automatically to https://localhost:3000/home in the browser bar, similarly for https://www.myapp.io/#/home . 因此, https://localhost:3000/#/home会自动更改为浏览器栏中的https://localhost:3000/home ,类似于https://www.myapp.io/#/home

However, directly entering https://localhost:3000/home or https://www.myapp.io/home in the browser will raise an error (I don't know how to turn previous <h1><%= message %></h1><h2><%= error.status %></h2><pre><%= error.stack %></pre> in error.ejs to error.html , so I don't have more details). 但是,在浏览器中直接输入https://localhost:3000/homehttps://www.myapp.io/home会引发错误(我不知道如何转动以前的<h1><%= message %></h1><h2><%= error.status %></h2><pre><%= error.stack %></pre> error.ejserror.html ,所以我没有更多细节)。

So now, the goal is to make https://localhost:3000/home and https://www.myapp.io/home work. 所以现在,目标是使https://localhost:3000/homehttps://www.myapp.io/home工作。

By following this thread , I added the follows to app.js : 通过关注这个主题 ,我在app.js添加了以下内容:

app.use('/js', express.static(__dirname + '/js'));
app.use('/dist', express.static(__dirname + '/../dist'));
app.use('/css', express.static(__dirname + '/css'));
app.use('/partials', express.static(__dirname + '/partials'));    
app.all('/*', function(req, res, next) {
    res.sendFile('index.html', { root: __dirname });
});

And in Apache of Mac, here is my httpd-vhosts.conf , after restarting apache , https://localhost:3000/home still returns an error. 在Apache的Mac中,这是我的httpd-vhosts.conf ,重新启动apachehttps://localhost:3000/home仍会返回错误。

<VirtualHost *:443>
    ServerName localhost
    DocumentRoot "/Users/SoftTimur"

    SSLEngine on
    SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
    SSLCertificateFile /etc/apache2/ssl/localhost.crt
    SSLCertificateKeyFile /etc/apache2/ssl/localhost.key

    <Directory "/Users/SoftTimur">
        RewriteEngine on

        # Don't rewrite files or directories
        RewriteCond %{REQUEST_FILENAME} -f [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^ - [L]

        # Rewrite everything else to index.html to allow html5 state links
        RewriteRule ^ index.html [L]

        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>
</VirtualHost>

In production, here is the NGINX server block. 在生产中,这是NGINX服务器块。 After restarting NGINX, https://www.myapp.io/home still returns an error. 重启NGINX后, https://www.myapp.io/home //www.myapp.io/home仍然会返回错误。

server {
    listen 443 ssl;

    server_name myapp.io www.myapp.io;

    ssl_certificate /etc/letsencrypt/live/myapp.io/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/myapp.io/privkey.pem;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:EC$
    ssl_session_timeout 1d;
    ssl_stapling on;
    ssl_stapling_verify on;
    add_header Strict-Transport-Security max-age=15768000;

    index index.html;

    root /opt/myapp;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location ~ /.well-known {
        allow all;
    }

    location / {
        proxy_set_header    Host                $host;
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto   $scheme;
        proxy_set_header    Accept-Encoding     "";
        proxy_set_header    Proxy               "";
        proxy_pass          https://127.0.0.1:3000;

        # These three lines added as per https://github.com/socketio/socket.io/issues/1942 to remove sock$

        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection "upgrade";
    }
}

Could anyone help? 有人可以帮忙吗?

try this in your express server 在您的快速服务器中试试这个

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

app.get('*', function (req, res) { res.sendFile(__dirname + '/views/index.html'); });

and in your angular app: 并在您的角度应用程序中:

$locationProvider.hashPrefix('!').html5Mode({
    enabled: true
});
$urlRouterProvider.otherwise('/');

and you still need the <base href="/"> in your index.html 你仍然需要index.html中的<base href="/">

let me know if this works for you 如果这对您有用,请告诉我

EDIT: 编辑:

I just found your app in https://github.com/chengtie/mini-mean , looks like your app.use order is wrong. 我刚刚在https://github.com/chengtie/mini-mean找到了您的应用,看起来您的app.use订单错误。 Please copy paste this in your express server and check if it's okay now. 请将其粘贴到您的快速服务器中,然后检查它是否正常。 pastebin 引擎收录

This might useful stuff, 这可能是有用的东西,

AngularJS routing without the hash '#' 没有散​​列'#'的AngularJS路由

Also, use this line in your express server file. 此外,在您的快速服务器文件中使用此行。 app.use(express.static(path.join(__dirname, 'client folder')));

this will directly finds your index.html file in that views folder and loads it 这将直接在该视图文件夹中找到您的index.html文件并加载它

  1. You don't need Apache or Nginx to run NodeJs in development, just node server.js is enough 您不需要Apache或Nginx在开发中运行NodeJ,只需node server.js就足够了
  2. Express gave you that error because you are using a deprecated API res.sendfile please use res.sendFile (capital F) Express给出了您的错误,因为您使用的是已弃用的API res.sendfile请使用res.sendFile(大写F)
  3. Some info for doing SPA: 做SPA的一些信息:
    • When you have the '#' in your URL, the browser interpret it as a local reference and thus, won't send new request to the server 当您在URL中有“#”时,浏览器会将其解释为本地引用,因此不会向服务器发送新请求
    • By enabling $locationProvider.html5Mode(true) you are now using html5 push state to navigate around your application history and (if I'm not mistaken you are happening to be using) angular effectively remove the '#' in url 通过启用$locationProvider.html5Mode(true)您现在使用html5推送状态来浏览您的应用程序历史记录(如果我没有弄错您正在使用)角度有效地删除了网址中的“#”
    • Without the '#' (hash-bang) browser will interpret it as a new request and send it to server, so you have to map all requests from server to your SPA entry file 没有'#'(hash-bang)浏览器会将其解释为新请求并将其发送到服务器,因此您必须将所有请求从服务器映射到SPA条目文件
    • For exact steps of replicating this behavior, consult this article: https://scotch.io/tutorials/pretty-urls-in-angularjs-removing-the-hashtag (the base href in your entry file is important) 有关复制此行为的确切步骤,请参阅以下文章: https//scotch.io/tutorials/pretty-urls-in-angularjs-removing-the-hashtag (输入文件中的基本href很重要)

If it's just about the #. 如果只是#。 You can remove it in Angular itself. 您可以在Angular中删除它。

Just inject locationProvider at your app entry and set htmlMode to true. 只需在您的应用程序条目中注入locationProvider并将htmlMode设置为true即可。 In your index.html set the baseUrl. 在index.html中设置baseUrl。

$locationProvider.html5Mode(true)

And in you index.html add: 在你index.html中添加:

<base href="/" />

That will generate your urls without the #. 这将生成没有#的网址。 Does that help? 这有帮助吗?

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

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