Good Day!
My colleague has a website node.js (next.js), his website works fine when we build and start thru console (npm run build and npm start).
We have hosted it in a Azure VM (Windows Server 2016 IIS, iisnode and urlrewrite installed), we created a pipeline and we are able to get the artifacts (".next" folder when we run the build) and deploy it to IIS however we still need a manual interaction to place the web.config. Below is the web.config
<!-- indicates that the hello.js file is a node.js application
to be handled by the iisnode module -->
<handlers>
<add name="iisnode" path="service-worker.js" verb="*" modules="iisnode" />
</handlers>
<!-- use URL rewriting to redirect the entire branch of the URL namespace
to hello.js node.js application; for example, the following URLs will
all be handled by hello.js:
http://localhost/node/express/myapp/foo
http://localhost/node/express/myapp/bar
-->
<rewrite>
<rules>
<rule name="AMS" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
But when we visit the website, it throws an error of 403 that need to supply the default page. (I'm lost here and not able to run his website thru IIS)
Note: His other website works fine (because it has a service-worker.js).
Anyone experience deploying the Next.JS to IIS? Thanks in Advance.
In the /public folder, create the following web.config to accept requests from /a/b/c and rewrite them to / where our NextJs code lives.
<?xml version="1.0"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="NextJs Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Just doing this should allow you to reload a page on a route like /products, but NextJs will render /, ie, the index page, because that's what our rewrite rule told it to deliver.
So, we need to create a body Component that takes a NextRouter as a prop then compare the window's url to the router's url. If they don't match, we need to change our client side route with router.push().
I'm using TypeScript so my body.tsx is
import * as React from 'react';
import { NextRouter } from 'next/router';
export default class Body extends React.Component<{router : NextRouter}>
{
componentDidMount()
{
if (window.location.pathname == this.props.router.pathname) return;
this.props.router.push(global.window.location.pathname);
}
render = () => this.props.children;
}
Then in _app.tsx, we simply need to wrap the main Component in our Body Component.
import { useRouter } from 'next/router'
import Head from 'next/head';
import Body from '../src/components/elements/body';
function MyApp({ Component, pageProps }) {
const router = useRouter();
return (
<>
<Head>
<title>NextJs on IIS</title>
</Head>
<Body router={router}>
<Component {...pageProps} />
</Body>
</>
)
}
export default MyApp
Run npm run build, and copy the /out folder to your IIS server.
Related
I have an app in the azure app service which has "index.html" setup as a default document in portal and also url rewrites in web-config (see below). If I go to the site with cleared history or chrome incognito mode it gives me a 404. I can hit the url directly on "mysite.com/index.html" and after that "mysite.com" will work too, but brand new browser session always 404.
I also have below in www_root in attempt to force "index.html" to load but no luck, any ideas?
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<!-- IIS URL Rewrite for react routes -->
<rewrite>
<rules>
<rule name="Angular Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Try by removing '/' in url=/index.html and add appendQueryString="true"
The default document is the web page that's displayed at the root URL for a website. The first matching file in the list is used. To add a new default document, click New document.
So, you could remove the above and then try adding> In the Azure portal, search for and select App Services, and then select your app. In the app's left menu, select Configuration > Default documents.
If the app uses modules that route based on URL instead of serving static content, there is no need for default documents.
To isolate, try to configure web.config similar to this:
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="SPA">
<match url=".*" />
<action type="Rewrite" url="index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Or If you wish to actually rewrite but not redirects, try enabling ARR with applicationHost.xdt file with in the site root folder. If you connect to your site using Kudu console, you will see the deployed files under your site\wwwroot folder - Kudu console (https://yoursite.scm.azurewebsites.net) > From the Kudu Console> Debug Console >> (CMD/PowerShell> Site > wwwroot. >> Shows-up all your deployment files.
Ok, this is similar to other questions out there but I am not familiar with url rewrite.
I am hosting (hopefully only for development and testing) a react application under IIS.
If hosted in the root of the site folder all is well using
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Static Assets" stopProcessing="true">
<match url="([\S]+[.](svg|js|css|png|gif|jpg|jpeg))" />
<action type="Rewrite" url="{R:1}" />
</rule>
<rule name="ReactRouter Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
But I need it to work in a subapplication. For instance: http://myserver:8888/myapp. Where myapp is the sub application.
IIS diagram:
Sites
- MySite
- MyApp
Better example of the url that includes the route: http://myserver:8888/myapp/1234/abcd.
1234 and abcd are route values/params.
contents of my app directory are:
index.html
main.a9e1df0325f4fdb57e7e.js
vendors~main.c8848853e10f698af19d.js
web.config
Thanks
Gina
You could host your app in any subapplication in iis but be careful to defining correct route for serving contents. It seems you want to host static content so you can't use route parameters in url hence these parameters are used by asp.net. Static content are served by iis. You can try this url for serving content in myapp:
http://myserver:8888/myapp/index.html
Hello I build a very basic Node.js app (without any framework),
I set up a route.
index.html and login.html
on my local machine (windows 10) its working fine. both files index.html and login.html show up in browser when I call them from url. like
localhost/myapp => loads index.html
localhost/myapp/login => loads login.html
Now I deploy it on Microsoft Azure, and now only index file is loading, when i try to load myapp.azurewebsites.net/login it said this : The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
I have a web.config file with these settings
<?xml version="1.0"?>
<configuration>
<system.webServer>
<staticContent>
<mimeMap fileExtension=".html" mimeType="text/html" />
</staticContent>
</system.webServer>
</configuration>
please guide me how to enable routing in node.js on azure. without any framework. there is no help on official docs.
thanks
well after a lot of search I figure out the solution.
you need to set web.config file from their demo project and upload into your own azure project.
https://github.com/Azure-Samples/nodejs-docs-hello-world/archive/master.zip
You could use the Azure Node JS Starter Site or Node JS Empty Web App.
In those projects you will find the right web.config file that you need to run Node applications in Azure.
Try to add below code in web.config file and see if it works.
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
For more details on this error follow this link.
I'm developing a single page app using angularJS(client) and mvc web api (server). I have two physical page first Login.html and second Index.html
when user successfully log in redirects to Index.html and other parts of my app load dynamically into div signed with ng-view inside Index.html page and I use AngularJS $routeProviderto configure my routes with their associated templates and controllers. I recently removed hash tag from url using $locationProvider.html5Mode(true); and adding <base href="/Index.html"> to head section of Index.html Page.I have a route that take a dynamic parameter like so Index.html/MetaDetails/123456 when I go to such page for first time every thing is fine but when refresh the page I receive iis 404 error
here is my route configuration using $routeProvider
App.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/Index.html', {
templateUrl: 'View/HomePage.html'
})
.when('/MetaDetails/:url', {
templateUrl: 'View/MetaDetails/MetaDetails.html'
}).when('/Logout', {
templateUrl: 'View/Users/logout.html',
controller: 'LogoutController'
}).when('/MetaCRUD', {
templateUrl: 'View/MetaDetails/MetaCRUD.html',
typeTemplate:'insert',
controller: 'MetaCRUDController'
}).when('/MetaCRUD/:url', {
templateUrl: 'View/MetaDetails/MetaCRUD.html',
typeTemplate: 'update',
controller: 'MetaCRUDController'
}).when('/MetaReport', {
templateUrl: 'View/Report/MasterReport.html',
controller: 'reportController'
})
.when('/404', {
templateUrl: 'View/ErrorPage.html',
})
.otherwise({
redirectTo: '/404'
});
$locationProvider.html5Mode(true);
});
I know it happens because it conflicts with iis routing and knows my route as a real physical page so most probable solution would be url rewriting I used following rewriting rule
<rule name="AngularJS Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
Update 2 :
then when I refresh or redirect from an other url my route doesn't change but Index.html is shown without it's css an js refrences included (totally devastated) as if it has no css and js and it's basically because it tries to read resources from host/metadetails/example.css or host/metadetails/example.js instead of host/example.js
how does it happen and how can i make it get resources from root not /metadetals path
what do you think would be the appropriate solution(which probably would be an iis url rewriting) to solve this isue
note that it's very important to me to keep my single page structure on the other hand when I navigate from one page to another for example from metaCRUD (index.html/MetaCRUD) to desired MetaDetails(index.html/MetaDetails/someid)
I dont want my page being post back at all just like when I used to use hash tag which every thing was fine and only templates and data changed with no post back
Update 3
I just figure out that the problem arises only when my route has parameter (index.html/MetaDetails/someid)
how can I rewrite this url to make iis not mistakenly recognize my parameter included route as physical path???
any help would be appreciated
It's nice how everyone tells you how to remove the hashtag, but not the fix of the refresh.
Here's what worked for me:
app.js: add "$locationProvider.html5Mode(true);" in app.config as first line.
index.html: add "" in your as the first line.
web.config: add the following at the end of your config:
<system.webServer>
<rewrite>
<rules>
<rule name="AngularJS Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
This worked for me. Apologies, the editor was a bit moody.
I am using a Rewrite rule in my web.config file for a node app running under issnode to point to my server.js file. myapp/* points to server.js.
<rule name="myapp" enabled="true">
<match url="myapp/*" />
<action type="Rewrite" url="server.js" />
</rule>
This has been working great www.mywebsite.com/myapp/ would load a run my app. What I wanted was to have a redirect from the root of the website so www.mywebsite.com/ would run my app. So I changed my web.config file
<rule name="myapp" enabled="true">
<match url="/*" />
<action type="Rewrite" url="server.js" />
</rule>
So this is running the server.js and serving up a my a static html file, the only problem is referencing any external files from my html file (css, js, images etc) Just get 500s for every request. I am using this to serve static files
var libpath = require('path');
var _path = "."; <-- This seems to be the problem
var uri = url.parse(req.url).pathname;
var filename = libpath.join(_path, uri);
fs.readFile(filename, "binary", function (err, file) {
if (err) {
res.writeHead(500, {
"Content-Type": "text/plain"
});
res.write(err + "\n");
res.end();
return;
}
var type = mime.lookup(filename);
res.writeHead(200, {
"Content-Type": type
});
res.write(file, "binary");
res.end();
});
break;
So my question is how to point to root of my node app / server to serve up static files.
Thanks
Jono
The best way to serve static content in iisnode is to configure the URL rewriting module such that the IIS static file handler handles requests for static content rather than node.js. Having IIS serve static content has a large performance benefit over serving these files using any node.js mechanisms due to kernel level optimizations around caching and just not having to break into JavaScript code.
For a boilerplate web.config configuration that achieves this see https://github.com/tjanczuk/iisnode/issues/160#issuecomment-5606547
I had some issues using the suggested rule config, so I made some changes:
<system.webServer>
<handlers>
<clear />
<add name="iisnode" path="/index.js" verb="*" modules="iisnode" />
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
</handlers>
<rewrite>
<rules>
<rule name="static">
<action type="Rewrite" url="www{REQUEST_URI}" />
</rule>
<rule name="serve-static" stopProcessing="true">
<conditions logicalGrouping="MatchAny">
<add input="{REQUEST_FILENAME}" matchType="IsFile" />
<add input="{REQUEST_URI}" pattern="^/www/$" />
</conditions>
</rule>
<rule name="node">
<action type="Rewrite" url="index.js" />
</rule>
</rules>
</rewrite>
</system.webServer>
First rule prefixes all requests with www, my client directory.
Second rule stops processing if the file exists or if the root path is requested
Third rule rewrites anything else to the name of my backend Node script so that it can be picked up by the iisnode handler.
Note the iisnode handler path is set to /index.js which seems to eliminate conflicts with client files of the same name.