Giter VIP home page Giter VIP logo

krabs's Introduction

Build Status e2e tests codecov NPM Downloads npm Commitizen friendly

Krabs is an enterprise-ready Express.js/Fastify middleware for serving thousands of different websites from a single Next.js instance.

Sponsors

Installation

Krabs is available on npm and can be installed as follows:

For Express.js (see on npm)

yarn add krabs

# or

npm install --save krabs

For Fastify (see on npm)

yarn add fastify-krabs

# or

npm insall --save fastify-krabs

Things to know

  • Krabs forces you to use a custom server. Therefore, deployments to Vercel are not supported.
  • _app and _document pages are common to every website.

Getting Started

You can watch a video introduction on YouTube:

Examples

Express.js example

Let's say that we want to support two different websites with just one Next.js instance, and serve them using just one Express.js server. Write the following configuration inside a .krabs.js or .krabs.config.js file inside of the root of your project:

module.exports = {
  tenants: [
    {
      name: 'website-1',
      domains: [
        {
          development: /dev\.[a-z]*\.local\.website-1\.com/, // Regex supported!
          staging: 'stage.website-1.com',
          production: 'website-1.com',
        },
      ],
    },
    {
      name: 'website-2',
      domains: [
        {
          development: 'local.website-2.com',
          staging: 'stage.website-2.com',
          production: /[\w|\d|-|_]+\.website-2.com/, // Regex supported!
        },
      ],
    },
  ],
};

Create an index.js file and fill it with the following content:

const express = require('express');
const next = require('next');
const krabs = require('krabs').default;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });

async function main() {
  try {
    await app.prepare();

    const handle = app.getRequestHandler();
    const server = express();

    server
      .get('*', (req, res) => krabs(req, res, handle, app))
      .listen(3000, () => console.log('server ready'));
  } catch (err) {
    console.log(err.stack);
  }
}

main();

Inside our .krabs.js file, we configured two tenants with two different name properties: website-1 and website-2. So now let's create two new folders inside of the Next.js' default pages/ directory:

pages/
  - _app.js
  - website-1
  - website-2

Feel free to add any page you want inside both of these folders, as they will be treated as they were the default Next.js' pages/ folder. Let's add the following content to pages/website-1/about.js:

function About() {
  return <div> About website 1 </div>;
}

export default About;

and the following code to pages/website-2/about.js:

function About() {
  return <div> This is website 2 </div>;
}

export default About;

Map local.website-1.com and local.website-2.com in your hosts file, then boot the server by typing:

node index.js

going to http://dev.pizza.local.website-1.com/about and http://local.website-2.com/about, you will see the components above rendered by the same Next.js instance!

Fastify example

Let's say that we want to support two different websites with just one Next.js instance, and serve them using just one Express.js server. Write the following configuration inside a .krabs.js or .krabs.config.js file inside of the root of your project:

module.exports = {
  tenants: [
    {
      name: 'website-1',
      domains: [
        {
          development: /dev\.[a-z]*\.local\.website-1\.com/, // Regex supported!
          staging: 'stage.website-1.com',
          production: 'website-1.com',
        },
      ],
    },
    {
      name: 'website-2',
      domains: [
        {
          development: 'local.website-2.com',
          staging: 'stage.website-2.com',
          production: /[\w|\d|-|_]+\.website-2.com/, // Regex supported!
        },
      ],
    },
  ],
};

Create an index.js file and fill it with the following content:

const fastify = require('fastify')({ trustProxy: true });
const next = require('next');
const krabs = require('../dist/fastify-krabs').default;

const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });

async function main() {
  try {
    await app.prepare();
    const handle = app.getRequestHandler();

    fastify
      .get('*', (request, reply) => krabs(request, reply, handle, app))
      .listen(3000, () => console.log('server ready'));
  } catch (err) {
    console.log(err.stack);
  }
}

main();

Inside our .krabs.js file, we configured two tenants with two different name properties: website-1 and website-2. So now let's create two new folders inside of the Next.js' default pages/ directory:

pages/
  - _app.js
  - website-1
  - website-2

Feel free to add any page you want inside both of these folders, as they will be treated as they were the default Next.js' pages/ folder. Let's add the following content to pages/website-1/about.js:

function About() {
  return <div> About website 1 </div>;
}

export default About;

and the following code to pages/website-2/about.js:

function About() {
  return <div> This is website 2 </div>;
}

export default About;

Map local.website-1.com and local.website-2.com in your hosts file, then boot the server by typing:

node index.js

going to http://dev.pizza.local.website-1.com/about and http://local.website-2.com/about, you will see the components above rendered by the same Next.js instance!

Documentation

You can find the full documentation (with real code examples) here!

License

Krabs is free as in freedom and licensed under the MIT license.


krabs's People

Contributors

kachar avatar micheleriva avatar stefano-regosa-deel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

krabs's Issues

Router push takes subdomain name?

I encountered the following case using router push redirects to the given route but adds the subdomain name, is this done on purpose? I am not sure if it's a krabs issue.

In my case I have following subdomain locally:

http://local.mickey.com:3000/login

on submit I do a simple react router push like this:

  const login = (e) => {
    e.preventDefault();
    router.push(`dashboard`);
  };

This redirects to following URL

http://local.mickey.com:3000/mickey/dashboard

which strangely shows the correct content / page. After I refresh this page it returns a 404.
The actual URL should be http://local.mickey.com:3000/dashboard (without the subdomain's name mickey)

If I add a slash to my router push like this:

  const login = (e) => {
    e.preventDefault();
    router.push(`/dashboard`);
  };

it redirects properly to this URL http://local.mickey.com:3000/dashboard

But adding a slash is "wrong" since adding it does a complete refresh of the next page.

If this is the indented behavior, is there a way to remove the subdomain's name here ....:3000/SUBDOMAIN/dashboard

May this happen because I have the login page inside my subdomain inside the pages directory so it default adds its name?

pages
  mickey
    login
    dashboard

putting it one level above would destroy the tenant's login behavior I try to accomplish.

NextJs's Link components do a full refresh

Hi again,

somehow the NextJs Link components do a full refresh, default NextJs applications does not have this behavior.
Not sure if that behavior is due to krabs.

In my case, I have the following setup

const navigation = [
  { name: 'Immobilien', href: '/real-estates', icon: FolderIcon, current: false },
  { name: 'Documents', href: '/documents', icon: InboxIcon, current: false },
  { name: 'Exports', href: '/exports', icon: ChartBarIcon, current: false },
]

    {navigation.map((item) => (
      <Link
        key={item.name}
        href={item.href}
        aria-current={item.current ? 'page' : undefined}
      >
        <a>
          <item.icon
            aria-hidden="true"
          />
          {item.name}
        </a>
      </Link>
    ))}

Error trying to set up kraber

I was trying to setup a simple kraber app but the setup fails.

I made the same steps you did in your tutorial video:

I get following error trying to start the server after setting up the index.js pages for the website-1 and website-2 subdomain.
The error occurs after running:

node index.jsto start the server

internal/modules/cjs/loader.js:311
throw err;
      ^

Error: Cannot find module '/Users/ut/Documents/code/private/personax/personaimo/node_modules/krabs/dist/index.js'. Please verify that the package.json has a valid "main" entry
    at tryPackage (internal/modules/cjs/loader.js:303:19)
    at Function.Module._findPath (internal/modules/cjs/loader.js:516:18)
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:867:27)
    at Function.Module._load (internal/modules/cjs/loader.js:725:27)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (/Users/umuttufanoglu/Documents/code/private/personax/personaimo/index.js:3:15)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32) {
  code: 'MODULE_NOT_FOUND',
  path: '/Users/ut/Documents/code/private/personax/personaimo/node_modules/krabs/package.json',
  requestPath: 'krabs'
}

nextjs 12.3.0 - Error: Cannot find module 'colors'

Followed installation correctly, using the latest version of next js.

Receiving the error

code: 'MODULE_NOT_FOUND'

node_modules/krabs/dist/utils/env/index.js
node_modules/krabs/dist/utils/tenants/findTenant.js',
node_modules/krabs/dist/express-krabs/index.js',
index.js'

Works with the example version of 9.5.5

Edit: I pulled another copy of the example and it works the first time. Not sure what the problem is now...

Edit 2: I had to run npm install colors to solve this...

npm install fails - Cannot read property 'version' of undefined

When I try to install the package using npm install krabs, the process fails with an error: Cannot read property 'version' of undefined. The error seems to be related to the arborist package. Here is the debug log, error occurs at line 217:

0 verbose cli [
0 verbose cli   'C:\\Program Files\\nodejs\\node.exe',
0 verbose cli   'C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
0 verbose cli   'install',
0 verbose cli   'krabs'
0 verbose cli ]
1 info using [email protected]
2 info using [email protected]
3 timing config:load:defaults Completed in 2ms
4 timing config:load:file:C:\Program Files\nodejs\node_modules\npm\npmrc Completed in 1ms
5 timing config:load:builtin Completed in 1ms
6 timing config:load:cli Completed in 2ms
7 timing config:load:env Completed in 1ms
8 timing config:load:file:D:\Coding\krabs-test\.npmrc Completed in 0ms
9 timing config:load:project Completed in 1ms
10 timing config:load:file:C:\Users\liamd\.npmrc Completed in 1ms
11 timing config:load:user Completed in 1ms
12 timing config:load:file:C:\Program Files\nodejs\etc\npmrc Completed in 0ms
13 timing config:load:global Completed in 0ms
14 timing config:load:cafile Completed in 0ms
15 timing config:load:validate Completed in 0ms
16 timing config:load:setUserAgent Completed in 0ms
17 timing config:load:setEnvs Completed in 2ms
18 timing config:load Completed in 11ms
19 verbose npm-session e0b79d589251c539
20 timing npm:load Completed in 26ms
21 timing arborist:ctor Completed in 2ms
22 timing idealTree:init Completed in 315ms
23 timing idealTree:userRequests Completed in 1ms
24 silly idealTree buildDeps
25 silly fetch manifest krabs@*
26 http fetch GET 200 https://registry.npmjs.org/krabs 78ms (from cache)
27 silly placeDep ROOT [email protected] OK for: [email protected] want: *
28 silly fetch manifest express@^4.17.1
29 silly fetch manifest krabs@^0.0.2
30 timing arborist:ctor Completed in 0ms
31 http fetch GET 304 https://registry.npmjs.org/express 523ms (from cache)
32 timing idealTree:#root Completed in 623ms
33 silly placeDep ROOT [email protected] OK for: [email protected] want: ^4.17.1
34 silly placeDep node_modules/krabs [email protected] OK for: [email protected] want: ^0.0.2
35 silly fetch manifest accepts@~1.3.7
36 silly fetch manifest [email protected]
37 silly fetch manifest [email protected]
38 silly fetch manifest [email protected]
39 silly fetch manifest content-type@~1.0.4
40 silly fetch manifest [email protected]
41 silly fetch manifest [email protected]
42 silly fetch manifest [email protected]
43 silly fetch manifest encodeurl@~1.0.2
44 silly fetch manifest escape-html@~1.0.3
45 silly fetch manifest finalhandler@~1.1.2
46 silly fetch manifest [email protected]
47 silly fetch manifest [email protected]
48 silly fetch manifest methods@~1.1.2
49 silly fetch manifest on-finished@~2.3.0
50 silly fetch manifest parseurl@~1.3.3
51 silly fetch manifest [email protected]
52 silly fetch manifest proxy-addr@~2.0.5
53 silly fetch manifest [email protected]
54 silly fetch manifest range-parser@~1.2.1
55 silly fetch manifest [email protected]
56 silly fetch manifest [email protected]
57 silly fetch manifest [email protected]
58 silly fetch manifest type-is@~1.6.18
59 silly fetch manifest [email protected]
60 silly fetch manifest vary@~1.1.2
61 silly fetch manifest next@^10.0.4
62 http fetch GET 304 https://registry.npmjs.org/accepts 385ms (from cache)
63 http fetch GET 304 https://registry.npmjs.org/merge-descriptors 373ms (from cache)
64 http fetch GET 304 https://registry.npmjs.org/methods 446ms (from cache)
65 http fetch GET 304 https://registry.npmjs.org/array-flatten 667ms (from cache)
66 http fetch GET 304 https://registry.npmjs.org/fresh 690ms (from cache)
67 http fetch GET 304 https://registry.npmjs.org/encodeurl 705ms (from cache)
68 http fetch GET 304 https://registry.npmjs.org/escape-html 711ms (from cache)
69 http fetch GET 304 https://registry.npmjs.org/finalhandler 712ms (from cache)
70 http fetch GET 304 https://registry.npmjs.org/content-type 781ms (from cache)
71 http fetch GET 304 https://registry.npmjs.org/body-parser 786ms (from cache)
72 http fetch GET 304 https://registry.npmjs.org/debug 779ms (from cache)
73 http fetch GET 304 https://registry.npmjs.org/content-disposition 822ms (from cache)
74 http fetch GET 304 https://registry.npmjs.org/cookie 820ms (from cache)
75 http fetch GET 304 https://registry.npmjs.org/cookie-signature 826ms (from cache)
76 http fetch GET 304 https://registry.npmjs.org/parseurl 811ms (from cache)
77 http fetch GET 304 https://registry.npmjs.org/on-finished 815ms (from cache)
78 http fetch GET 304 https://registry.npmjs.org/path-to-regexp 820ms (from cache)
79 http fetch GET 304 https://registry.npmjs.org/proxy-addr 824ms (from cache)
80 http fetch GET 304 https://registry.npmjs.org/range-parser 819ms (from cache)
81 http fetch GET 304 https://registry.npmjs.org/qs 825ms (from cache)
82 http fetch GET 304 https://registry.npmjs.org/safe-buffer 824ms (from cache)
83 http fetch GET 304 https://registry.npmjs.org/send 824ms (from cache)
84 http fetch GET 304 https://registry.npmjs.org/serve-static 824ms (from cache)
85 http fetch GET 304 https://registry.npmjs.org/vary 819ms (from cache)
86 http fetch GET 304 https://registry.npmjs.org/type-is 827ms (from cache)
87 http fetch GET 304 https://registry.npmjs.org/utils-merge 830ms (from cache)
88 http fetch GET 304 https://registry.npmjs.org/next 839ms (from cache)
89 silly timing Tried to end timer that doesn't exist: idealTree:#root
90 silly placeDep ROOT [email protected] OK for: [email protected] want: ~1.3.7
91 silly placeDep node_modules/express [email protected] OK for: [email protected] want: 1.1.1
92 silly placeDep ROOT [email protected] OK for: [email protected] want: 1.19.0
93 silly placeDep ROOT [email protected] OK for: [email protected] want: 0.5.3
94 silly placeDep ROOT [email protected] OK for: [email protected] want: ~1.0.4
95 silly placeDep ROOT [email protected] OK for: [email protected] want: 0.4.0
96 silly placeDep ROOT [email protected] OK for: [email protected] want: 1.0.6
97 silly placeDep ROOT [email protected] OK for: [email protected] want: 2.6.9
98 silly placeDep ROOT [email protected] OK for: [email protected] want: ~1.0.2
99 silly placeDep ROOT [email protected] OK for: [email protected] want: ~1.0.3
100 silly placeDep ROOT [email protected] OK for: [email protected] want: ~1.1.2
101 silly placeDep ROOT [email protected] OK for: [email protected] want: 0.5.2
102 silly placeDep ROOT [email protected] OK for: [email protected] want: 1.0.1
103 silly placeDep ROOT [email protected] OK for: [email protected] want: ~1.1.2
104 silly placeDep ROOT [email protected] OK for: [email protected] want: ~2.3.0
105 silly placeDep ROOT [email protected] OK for: [email protected] want: ~1.3.3
106 silly placeDep ROOT [email protected] OK for: [email protected] want: 0.1.7
107 silly placeDep ROOT [email protected] OK for: [email protected] want: ~2.0.5
108 silly placeDep ROOT [email protected] OK for: [email protected] want: 6.7.0
109 silly placeDep ROOT [email protected] OK for: [email protected] want: ~1.2.1
110 silly placeDep node_modules/express [email protected] OK for: [email protected] want: 5.1.2
111 silly placeDep ROOT [email protected] OK for: [email protected] want: 0.17.1
112 silly placeDep ROOT [email protected] OK for: [email protected] want: 1.14.1
113 silly placeDep ROOT [email protected] OK for: [email protected] want: ~1.6.18
114 silly placeDep ROOT [email protected] OK for: [email protected] want: 1.0.1
115 silly placeDep ROOT [email protected] OK for: [email protected] want: ~1.1.2
116 silly fetch manifest mime-types@~2.1.24
117 silly fetch manifest [email protected]
118 silly fetch manifest [email protected]
119 silly fetch manifest [email protected]
120 silly fetch manifest [email protected]
121 silly fetch manifest [email protected]
122 silly fetch manifest forwarded@~0.1.2
123 silly fetch manifest [email protected]
124 silly fetch manifest destroy@~1.0.4
125 silly fetch manifest [email protected]
126 silly fetch manifest [email protected]
127 silly fetch manifest [email protected]
128 http fetch GET 304 https://registry.npmjs.org/negotiator 127ms (from cache)
129 http fetch GET 304 https://registry.npmjs.org/ee-first 180ms (from cache)
130 http fetch GET 304 https://registry.npmjs.org/mime-types 217ms (from cache)
131 http fetch GET 304 https://registry.npmjs.org/mime 205ms (from cache)
132 http fetch GET 304 https://registry.npmjs.org/media-typer 208ms (from cache)
133 http fetch GET 304 https://registry.npmjs.org/ipaddr.js 224ms (from cache)
134 http fetch GET 304 https://registry.npmjs.org/ms 230ms (from cache)
135 http fetch GET 304 https://registry.npmjs.org/destroy 226ms (from cache)
136 http fetch GET 304 https://registry.npmjs.org/http-errors 247ms (from cache)
137 http fetch GET 304 https://registry.npmjs.org/forwarded 234ms (from cache)
138 http fetch GET 304 https://registry.npmjs.org/raw-body 242ms (from cache)
139 timing idealTree:node_modules/express Completed in 294ms
140 silly placeDep ROOT [email protected] OK for: [email protected] want: ~2.1.24
141 silly placeDep ROOT [email protected] OK for: [email protected] want: 0.6.2
142 silly fetch manifest [email protected]
143 http fetch GET 304 https://registry.npmjs.org/mime-db 96ms (from cache)
144 timing idealTree:node_modules/accepts Completed in 100ms
145 silly placeDep node_modules/body-parser [email protected] OK for: [email protected] want: 1.7.2
146 silly placeDep node_modules/body-parser [email protected] OK for: [email protected] want: 2.4.0
147 silly fetch manifest [email protected]
148 http fetch GET 304 https://registry.npmjs.org/inherits 102ms (from cache)
149 timing idealTree:node_modules/body-parser Completed in 112ms
150 silly placeDep node_modules/content-disposition [email protected] OK for: [email protected] want: 5.1.2
151 timing idealTree:node_modules/content-disposition Completed in 1ms
152 timing idealTree:node_modules/content-type Completed in 0ms
153 timing idealTree:node_modules/cookie Completed in 0ms
154 timing idealTree:node_modules/cookie-signature Completed in 0ms
155 silly placeDep ROOT [email protected] OK for: [email protected] want: 2.0.0
156 timing idealTree:node_modules/debug Completed in 2ms
157 timing idealTree:node_modules/encodeurl Completed in 0ms
158 timing idealTree:node_modules/escape-html Completed in 0ms
159 timing idealTree:node_modules/finalhandler Completed in 0ms
160 timing idealTree:node_modules/fresh Completed in 0ms
161 timing idealTree:node_modules/merge-descriptors Completed in 0ms
162 timing idealTree:node_modules/methods Completed in 0ms
163 silly placeDep ROOT [email protected] OK for: [email protected] want: 1.46.0
164 timing idealTree:node_modules/mime-types Completed in 1ms
165 timing idealTree:node_modules/mime-db Completed in 0ms
166 timing idealTree:node_modules/ms Completed in 0ms
167 timing idealTree:node_modules/negotiator Completed in 0ms
168 silly placeDep ROOT [email protected] OK for: [email protected] want: 1.1.1
169 timing idealTree:node_modules/on-finished Completed in 1ms
170 timing idealTree:node_modules/ee-first Completed in 0ms
171 timing idealTree:node_modules/parseurl Completed in 0ms
172 timing idealTree:node_modules/path-to-regexp Completed in 0ms
173 silly placeDep ROOT [email protected] OK for: [email protected] want: ~0.1.2
174 silly placeDep ROOT [email protected] OK for: [email protected] want: 1.9.1
175 timing idealTree:node_modules/proxy-addr Completed in 1ms
176 timing idealTree:node_modules/forwarded Completed in 0ms
177 timing idealTree:node_modules/ipaddr.js Completed in 0ms
178 timing idealTree:node_modules/qs Completed in 0ms
179 timing idealTree:node_modules/range-parser Completed in 0ms
180 silly placeDep ROOT [email protected] OK for: [email protected] want: ~1.0.4
181 silly placeDep ROOT [email protected] OK for: [email protected] want: 1.6.0
182 silly placeDep node_modules/send [email protected] OK for: [email protected] want: 2.1.1
183 timing idealTree:node_modules/send Completed in 4ms
184 timing idealTree:node_modules/destroy Completed in 0ms
185 timing idealTree:node_modules/mime Completed in 0ms
186 timing idealTree:node_modules/serve-static Completed in 0ms
187 silly placeDep ROOT [email protected] OK for: [email protected] want: 0.3.0
188 timing idealTree:node_modules/type-is Completed in 1ms
189 timing idealTree:node_modules/media-typer Completed in 0ms
190 timing idealTree:node_modules/utils-merge Completed in 0ms
191 timing idealTree:node_modules/vary Completed in 0ms
192 silly placeDep node_modules/body-parser [email protected] OK for: [email protected] want: 2.0.3
193 timing idealTree:node_modules/body-parser/node_modules/http-errors Completed in 10ms
194 timing idealTree:node_modules/body-parser/node_modules/inherits Completed in 0ms
195 timing idealTree:node_modules/body-parser/node_modules/raw-body Completed in 0ms
196 timing idealTree:node_modules/content-disposition/node_modules/safe-buffer Completed in 0ms
197 timing idealTree:node_modules/express/node_modules/array-flatten Completed in 0ms
198 timing idealTree:node_modules/express/node_modules/safe-buffer Completed in 0ms
199 timing idealTree:node_modules/send/node_modules/ms Completed in 0ms
200 timing idealTree:buildDeps Completed in 2168ms
201 timing idealTree:fixDepFlags Completed in 12ms
202 timing idealTree Completed in 2504ms
203 timing reify:loadTrees Completed in 2506ms
204 timing reify:diffTrees Completed in 11ms
205 silly reify moves {}
206 timing reify:retireShallow Completed in 0ms
207 timing reify:createSparse Completed in 0ms
208 timing reify:loadBundles Completed in 0ms
209 timing reify:unpack Completed in 0ms
210 timing reify:unretire Completed in 0ms
211 timing build:queue Completed in 0ms
212 timing build:deps Completed in 1ms
213 timing build Completed in 1ms
214 timing reify:build Completed in 1ms
215 timing reify:trash Completed in 0ms
216 timing command:install Completed in 2550ms
217 verbose stack TypeError: Cannot read property 'version' of undefined
217 verbose stack     at Arborist.[saveIdealTree] (C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\reify.js:875:33)
217 verbose stack     at C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\reify.js:131:39
217 verbose stack     at async Arborist.reify (C:\Program Files\nodejs\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\reify.js:127:5)
217 verbose stack     at async install (C:\Program Files\nodejs\node_modules\npm\lib\install.js:38:3)
218 verbose cwd D:\Coding\krabs-test
219 verbose Windows_NT 10.0.18363
220 verbose argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "krabs"
221 verbose node v12.19.0
222 verbose npm  v7.5.4
223 error Cannot read property 'version' of undefined
224 verbose exit 1

How to add a CMS like Strapi

Hi, not an "issue", but I was wondering how one should add a cms like strapi to an next app using krabs, since the app already contains a backend with express.
Or does it not make sense to use this and headless cms like strapi?

UnhandledPromiseRejectionWarning: fast_memoize_1.default is not a function

Hi, I just ran into the following issue after updating Krabs to the latest v0.013! Even though the server is ready, it fails to load its tenants. I'm using an async config btw.

info  - server ready on port 3000
(node:18300) UnhandledPromiseRejectionWarning: TypeError: fast_memoize_1.default is not a function
    at D:\Git Repos\WireApps\webshop-next-app\node_modules\krabs\dist\index.js:60:71  
    at step (D:\Git Repos\WireApps\webshop-next-app\node_modules\krabs\dist\index.js:33:23)
    at Object.next (D:\Git Repos\WireApps\webshop-next-app\node_modules\krabs\dist\index.js:14:53)
    at D:\Git Repos\WireApps\webshop-next-app\node_modules\krabs\dist\index.js:8:71   
    at new Promise (<anonymous>)
    at __awaiter (D:\Git Repos\WireApps\webshop-next-app\node_modules\krabs\dist\index.js:4:12)
    at krabs (D:\Git Repos\WireApps\webshop-next-app\node_modules\krabs\dist\index.js:55:12)
    at D:\Git Repos\WireApps\webshop-next-app\server.js:16:31
    at Layer.handle [as handle_request] (D:\Git Repos\WireApps\webshop-next-app\node_modules\express\lib\router\layer.js:95:5)   
    at next (D:\Git Repos\WireApps\webshop-next-app\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (D:\Git Repos\WireApps\webshop-next-app\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (D:\Git Repos\WireApps\webshop-next-app\node_modules\express\lib\router\layer.js:95:5)   
    at D:\Git Repos\WireApps\webshop-next-app\node_modules\express\lib\router\index.js:281:22
    at param (D:\Git Repos\WireApps\webshop-next-app\node_modules\express\lib\router\index.js:354:14)
    at param (D:\Git Repos\WireApps\webshop-next-app\node_modules\express\lib\router\index.js:365:14)
    at Function.process_params (D:\Git Repos\WireApps\webshop-next-app\node_modules\express\lib\router\index.js:410:3)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:18300) UnhandledPromiseRejectionWarning: Unhandled 
promise rejection. This error originated either by throwing inside of an async function without a catch block, or 
by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` 
(see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 13)
(node:18300) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

krabs.config.js

const tenant = require("./modules/tenant.module");

module.exports = async () => await tenant.getAllTenants();

package.json - scripts

"scripts": {
    "dev": "NODE_ENV=dev node server.js",
    "build": "next build",
    "nextstart": "next start",
    "start": "NODE_ENV=prod node server.js"
  },

Slugs not working?

Hi Michel! I watched your video and have implemented a 2 tenant nextjs krabs based express server. I want to keep as much as possible within SSG. I'm having trouble with slugs though. I watched your example pretty carefully on YouTube, but you never showed whether slugs actually do work. I saw you created pages/veggies/blog/[slug].js. And you showed what happens when you click the Post components before you created the slug. But then you never showed what happened once the slug has been created.

Maybe I'm doing it wrong, but I can't figure out how to get the slug to work. I keep getting incompatible 'href' and 'as' values errors:

Uncaught (in promise) Error: The provided `as` value (/blog/post1) is incompatible with the `href` value (/website1/blog/[slug]). Read more: https://nextjs.org/docs/messages/incompatible-href-as

I've tried messing with different href and as values, but I can't figure out the right combination to get this working. Any ideas?

'Common pages' functionality

Hi there!

I am currently working on a project that uses Next.js and I want to make use of Krabs for a multi-tenant approach. One thing I wanted to do was to have what I call 'common pages' between all the tenants. For example creating a resources page in the default Next.js pages directory would then allow that page to be used by all tenants.

I have a fork of the repo and believe that I have been able to achieve this by passing an extra options parameter in to the default krabs() function call. The options parameter is an object that currently contains a commonPages boolean, this could be extended going forward. The update to the utils/routes/resolve.ts file is as follows:

const fs = require('fs')
const path = require('path')

export function resolveRoutes(tenantName: string, pathname: string, commonPages: boolean | undefined): string {
  const pageExistsInTenant = fs.existsSync(path.join(process.cwd(), 'pages', tenantName, `${pathname}.js`));

  if(commonPages && !pageExistsInTenant && pathname !== '/') {
    return `${pathname}`
  }

  return pathname === '/' ? `/${tenantName}` : `/${tenantName}${pathname}`;
}

export default resolveRoutes;

As you can see the modification to the function is minor but offers that little bit more flexibility.

I would love to hear any and all of your feedback on what you think of potentially adding this functionality to Krabs.

How to tenants for subdomains or custom domain in the production?

I found this library is working superbly in the development mode. but I am stuck in the production mode on my custom server.
I don't know how can I add dynamically add subdomains or custom domains on my custom hosting server.

Should I change DNS settings? or add manually subdomains in my hosting panel? or how to point custom domain name?
Please helpout...

Tenant url does not work locally

I set up kraber nextjs with express, my server runs properly. This is my .kraber.js file

module.exports = {
  tenants: [
    {
      name: 'website-1',
      domains: [
        {
          development: /dev\.[a-z]*\.local\.website-1\.com/, // Regex supported!
          staging: 'stage.website-1.com',
          production: 'website-1.com',
        },
      ],
    },
    {
      name: 'website-2',
      domains: [
        {
          development: 'local.website-2.com',
          staging: 'stage.website-2.com',
          production: /[\w|\d|-|_]+\.website-2.com/, // Regex supported!
        },
      ],
    },
  ],
};

Inside pagesI created the folder website-1 and website-2 with a simple index.js page

I can't access the page using following URLs locally:

dev.website-1.com:3000
local.website-1.com:3000

nor

dev.website-2.com:3000
local.website-2.com:3000

What am I missing?

Example project does not work

Hi all,
I've run the example projects as documented in the readme as well as the video and simply cannot get them to work.

browser returning "This site can’t be reached Check if there is a typo in dev.pizza.local.website-1.com.
DNS_PROBE_FINISHED_NXDOMAIN"

Has anyone else experienced this?

rewrites dont work

I want to add certain rewrites to one of my domains and it doesn't seem to work, this is what my next.config.js looks like:

module.exports = {
    async rewrites() {
        return [
            {
                source: '/someroute',
                destination: '/somepage',
            },
        ]
    },
}

I also tried adding the tenant name before and it also didn't work:

module.exports = {
    async rewrites() {
        return [
            {
                source: '/tenant/someroute',
                destination: '/tenant/somepage',
            },
        ]
    },
}

any help would be appreciated

500 status code without error message on Next.js 10.2.0

I have a "hello world" app created using npx create-next-app. I've added the krabs package and the .krabs.js file as per the tutorial, but when running my custom server I just keep getting an empty 500 status code page without any additional errors. Could you please make sure that things still work and that relevant error messages are printed when an error occurs?

Guide of how to deloy this

Not an issue but I cant change the label to this, could you provide a guide on how to properly deploy this on platforms like digital ocean. I am not sure how to configure the subdomains and build nextjs since I have to run express.

I "simple" guide would be awesome with multiple subdomain ❀️

Btw cool project πŸ‘

API Routes

With this package installed, any API routes that you create will no longer be available. Could there be a way to get around this?

I'm trying to create a project that uses APIs (all APIs can use the same domain that the user is currently on - e.g. (https://site1.com/api and https://site2.com/api).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.