DEV Community

Cover image for Deploying Sveltekit on IIS !
Nutchapon Makelai
Nutchapon Makelai

Posted on • Edited on

Deploying Sveltekit on IIS !

This is will be long article because it a self note for deploying Sveltekit project (as node project) on IIS version 10.
For a while I searching thru the internet and asking in svelte discord (so good community , if you're svelter don't miss to join in) I found out it have little information about how to deploying Sveltekit on IIS , may be I've so many conditions and requirements to made Sveltekit project working on my IIS server.


Conditions and Requirements

  1. running with one port and separate each project by sub-directory.
    ex.
    projectA ==> https://my.testsites.com:443/projectA
    projectB ==> https://my.testsites.com:443/projectB

  2. Need to be Server side rendering (SSR) which is Sveltekit project suppose to be.

  3. Any form actions are not blocked by Cross-site Request Forgery (CSRF) protection of Sveltekit project.


Prerequisites

after install IIS


How to step by step

  • run npm i in your sveltekit project folder
  • installing additional dependencies
    • adapter-node for sveltekit npm i -D @sveltejs/adapter-node
    • dotenv npm i dotenv
  • setup .env file in your root folder of your project and put this in your .env file
ORIGIN=http://localhost:PORT_OF_SITES
Enter fullscreen mode Exit fullscreen mode

while PORT_OF_SITES will be your port number of IIS site you want to deploy to let say it is 443 then it will be

ORIGIN=http://localhost:443
Enter fullscreen mode Exit fullscreen mode

this will be using after we have deploy Svletekit project to IIS and prevent CSRF blocked after any form actions

  • In root folder of your project find svelte.config.js and adding adapter-node and set base path to made it support a sub-directory in Sveltekit, let change all code inside like this
import adapter from '@sveltejs/adapter-node';

export default {
    kit: {
        adapter: adapter(),
        paths: {
            relative: false,
            base: '/NAME_OF_SUB-DIRECTORY'
        }
    }
};
Enter fullscreen mode Exit fullscreen mode

while NAME_OF_SUB-DIRECTORY will specifies where your app is served from and allows the app to live on a non-root path
ex. you want your site address like https://my.sites.com/svelteiis then svelte.config.js code will be like this

import adapter from '@sveltejs/adapter-node';

export default {
    kit: {
        adapter: adapter(),
        paths: {
            relative: false,
            base: '/svelteiis'
        }
    }
};
Enter fullscreen mode Exit fullscreen mode
  • after we adding adapter-node and adding base path we need to prepend all root-relative links with the base value or they will point to the root of your domain, not your base path (this is how the Sveltekit and browser work)

in src\routes\Header.svelte, src\routes\about\+page.svelte and src\routes\sverdle\+page.svelte we will adding import { base } from '$app/paths'; in <script> tag and adding every <a> tag with {base}
ex. <a href="{base}/">Home</a>, {base}/about">About</a>

  • next we will build our project as a node project by using npm run build and let adapter-node handle it's job . . . . . after some times you will have a build folder appear in your root project like image below

 raw `build` endraw  folder

  • let change side to config our IIS , firstly open our IIS and on your left pane just opening till you seen Default Web Site just right click on it and click explore like image below

explore a Default Web Site in IIS

-it will open a new window of file explorer with path C:\inetpub\wwwroot(let note this as a wwwroot folder) after that you can copy a build folder that we has created earlier in our Sveltekit project folder and let changing it name form build to a name of what your sub-directory you want that will match with base path that we config earlier or it cause some issue on navigating to your site!
after this step your wwwroot folder will be like image below

wwwroot folder

**you can deploy your project on new IIS site too by creating a new site in IIS and set physicals path to your deploy folder and bring your build folder into there and following the step by changing build folder name.

  • next we need to copy 2 files form your root project folder, that is .env file and package.json file and bring it to your deploying folder in wwwroot and running just npm i --omit=dev in this folder to made node downloading only required dependencies after running npm creating new web.config file and adding this code into your web.config file
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <webSocket enabled="false" />
    <handlers>
      <add name="iisnode" path="server.cjs" verb="*" modules="iisnode" />
    </handlers>
    <iisnode node_env="production" nodeProcessCommandLine="C:\Program Files\nodejs\node.exe" />
    <rewrite> 
        <rules>             
            <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
                <match url="^server.cjs\/debug[\/]?" />
                <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
            </rule>

            <rule name="StaticContent">
                <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                <action type="Rewrite" url="public{PATH_INFO}" />
            </rule>

            <rule name="DynamicContent">
                <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                </conditions>
                <action type="Rewrite" url="server.cjs" />
            </rule> 
        </rules>
        <outboundRules>
            <rule name="back">
                <match serverVariable="RESPONSE_Location" pattern="(.*)/server.cjs" />
                <action type="Rewrite" value="{R:1}" />
            </rule>
        </outboundRules>
    </rewrite>  
    <defaultDocument>
        <files>
            <add value="server.cjs" />
        </files>
    </defaultDocument>
    <security>
      <requestFiltering>
        <hiddenSegments>
          <remove segment="bin" />
        </hiddenSegments>
        <requestLimits maxAllowedContentLength="4294967295" />
      </requestFiltering>
    </security>
    <httpErrors existingResponse="PassThrough" />
  </system.webServer>
</configuration>
Enter fullscreen mode Exit fullscreen mode

after this config your Sveltekit deploy folder will be like a image below

in project deploy folder

  • last but not least we need to have some JavaScript file that will be running after iisnode calling to our project , that made our project can adjust some environment setting let create a new file name server.cjs or any other name but if you change the name you need to put that name into a web.config file from earlier (try search and replace server.cjs with your new file's name in web.config) after creating a server.cjs file add this code below to your file
require('dotenv').config();
const express = require('express')

import('./handler.js')
    .then((handler) => {
        const app = express();
        // Custom middleware to make routing case-insensitive
        app.use((req, res, next) => {
            const urlSegments = req.url.split('/');
            urlSegments[1] = urlSegments[1].toLowerCase();
            req.url = urlSegments.join('/');
            next();
        });

        // let SvelteKit handle everything else, including serving prerendered pages and static assets
        app.use(handler.handler);

        app.listen(process.env.PORT, () => {
            console.log(
                'app start on port ' + process.env.PORT
            );
        });

    }).catch((err) => console.error(err));
Enter fullscreen mode Exit fullscreen mode

this will made your .env file that you copying from earlier working as aspect and will set your origin of project to prevent CSRF protection from a form actions of the project itself and it will made your site can accessing with case insensitive url at a first sub-directory.
by the way you can disabled case insensitive by comment out below code in server.cjs

app.use((req, res, next) => {
            const urlSegments = req.url.split('/');
            urlSegments[1] = urlSegments[1].toLowerCase();
            req.url = urlSegments.join('/');
            next();
        }); 
Enter fullscreen mode Exit fullscreen mode

now inside the project folder in wwwroot will look like this

Image description

after that you can try going to the site that you have deploy by go to
http://localhost/NAME_OF_SUB-DIRECTORY or http://localhost:YOUR_IIS_PORT/NAME_OF_SUB-DIRECTORY
and finally you has achieved Sveltekit deploying on IIS !


If you has any question or suggestion on my walkthrough feel free to giving me a comment below. ;)

Thanks you
Have a nice day and keep coding

Top comments (0)