DEV Community

Patryk Tomczyk
Patryk Tomczyk

Posted on

Why dependencies matter? Deploy your Nuxt SSR (universal) app to Vercel Now.

There are plenty of instructions on how to deploy your Nuxt application to Vercel. However, users with more demanding setup have a hard time to deploy their Nuxt applications quickly. One of these setups is universal mode, allowing to use Server Side Rendering, which can be a little tricky.

I want to deploy Now!

For those of you, who came here to get help with deploying the app quickly, there are two simple steps.

  1. Create an account on Vercel and give access to your repository.

  2. Add now.json file in root of your project:

{
  "version": 2,
  "builds": [
    {
      "src": "nuxt.config.js",
      "use": "@nuxtjs/now-builder",
      "config": {}
    }
  ]
}

And basically, that's it. Now Builder takes care of everything else and after the push, Vercel starts the deploy.

But at this point, you may experience two problems.

The first one is that the build script is not invoked - Now builder runs its own nuxt build step so that's something you may struggle with. Solution for this is to add now-build script to your package.json with anything you'd like to do before nuxt build is being invoked.

The other one is tougher - app deployment on Vercel terminates with the following message:

Error: The Serverless Function "index" is 82.5mb, which exceeds the maximum size limit of 50mb.

You must be thinking - What the heck? I wrote a light Nuxt application, how is this possible that it takes so much space?

This one is the actual reason why I started writing this article, so my thoughts on that later, now how to fix it?

I like simple tips, which are making a huge difference, this is one of them.

Move all your dependencies into devDependencies, remove yarn.lock file (or package-lock.json) and run yarn (or npm install) to regenerate a new one. Commit, push, and it's done.

As an example here's the repository, on which I wanted to deploy Shopware PWA to Vercel, but any Nuxt project with universal mode will work.

You may wonder why moving dependencies into devDependencies helped

So if you're still reading, we'll jump a little deeper into the subject. When you're learning about dependencies and devDependencies, the overall explanation is that dependencies should be used for packages, which are required during runtime, and devDependencies should contain those, which are used only for development.

Easy, simple, clear, but...

What does it mean that we need to use dependency at runtime?

Most often, it means that we have something like require('some-package') in our code. Node searches in node_modules for that package and includes it at the runtime. So you could deploy your node application to the server, run npm install --production and then npm would load into node_modules only packages from dependencies, and theirs dependencies (as of course required for runtime) and so on... As we all know node_modules can be huge. Running --production flag on node applications on servers makes sense.

It's not the case anymore with modern web applications though. We use bundlers now, we use ESM modules and importing things instead of requiring them. Nuxt is using Webpack under the hood, so everything necessary for the application to run is statically analyzed, propagated into chunks and transformed to build/ dist directories. There's no more calling node_modules on runtime.

All you're dependencies are devDependencies as are used only during build of your application.

And Vercel is following these rules. That's why even if your built application is maybe few MB it shows you enormous size - simply assume that you're dependency setup is used during runtime, so it's a part of the application size.

So when should I use dependencies in my web application?

Never :) Most of the time it's not important; most of the apps are not even using SSR, just simple uploads built dist folder to CDN. And for building, you'll load all the dependencies either way.

A little reminder for library authors

Everything you'll put into dependencies for your package will be loaded with the installation. Seems obvious, but sometimes people forget about that. It's not that you should not add there anything and build your lib now to contain all the necessary dependencies. It would cause code duplication as bundlers can't tell if it's your code or other lib used in the project as well. No one want's that. There's a simple rule for that.

My library needs for a user to have installed dependency X - if so, we don't want to write in our quick start section "Install X,Y,Z in order to run". We're adding them to dependencies section, and until they are needed to run your lib, it's their place.

How contributors may help with that?

Jump into Open Source projects. Check out dependencies sections of their packages. Confront them with code. It usually doesn't require in-depth project knowledge. Maybe try Bundlephobia to see if any of these dependencies have a lighter alternative in the Similar Packages section.

Try to help by providing a PR, if it's complicated, you may create an Issue where you can discuss your findings. There's no point of any kind of shaming that your package has this HUGE dependency. Be polite; everyone's doing their best.

Discussion (4)

Collapse
xererske profile image
xererske

Really liked your article. It is the exact same problem I am facing.. I tried to do the same and move all my dependencies to the devDependencies, only I get an 'Nuxt Internal Server Error'.

This is the log from Vercel:

16:09:12.030 Cloning github.com/xererske/enabl-nuxt (Branch: main, Commit: c0d66d7)
16:09:12.740 Cloning completed in 710ms
16:09:12.744 Analyzing source code...
16:09:12.747 Warning: Due to `builds` existing in your configuration file, the Build and Development Settings defined in your Project Settings will not apply. Learn More: https://vercel.link/unused-build-settings
16:09:14.284 Installing build runtime...
16:09:17.339 Build runtime installed: 3054.768ms
16:09:17.985 Looking up build cache...
16:09:18.392 Build cache found. Downloading...
16:09:22.398 Build cache downloaded [76.60 MB]: 4005.284ms
16:09:23.056 [log] Running with @nuxt/vercel-builder version 0.18.1
16:09:23.056 [log] ----------------- Prepare build -----------------
16:09:23.057 [log] Downloading files...
16:09:23.057 [log] Working directory: /vercel/workpath0
16:09:23.061 [log] Using yarn
16:09:23.063 [info] Prepare build took: 6.435424 ms
16:09:23.063 [log] ----------------- Install devDependencies -----------------
16:09:23.064 [log] Using cached node_modules_dev
16:09:23.378 yarn install v1.22.4
16:09:23.499 [1/5] Resolving packages...
16:09:24.507 [2/5] Fetching packages...
16:09:58.621 info fsevents@2.3.1: The platform "linux" is incompatible with this module.
16:09:58.621 info "fsevents@2.3.1" is an optional dependency and failed compatibility check. Excluding it from installation.
16:09:58.653 info fsevents@1.2.13: The platform "linux" is incompatible with this module.
16:09:58.653 info "fsevents@1.2.13" is an optional dependency and failed compatibility check. Excluding it from installation.
16:09:58.655 [3/5] Linking dependencies...
16:09:58.660 warning "@nuxtjs/eslint-config > eslint-plugin-vue@6.2.2" has incorrect peer dependency "eslint@^5.0.0 || ^6.0.0".
16:09:58.662 warning "@nuxtjs/eslint-module > eslint-loader@4.0.2" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
16:09:58.662 warning " > @vue/test-utils@1.1.2" has unmet peer dependency "vue@2.x".
16:09:58.662 warning " > @vue/test-utils@1.1.2" has unmet peer dependency "vue-template-compiler@^2.x".
16:09:58.662 warning " > babel-core@7.0.0-bridge.0" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.662 warning " > babel-jest@26.6.3" has unmet peer dependency "@babel/core@^7.0.0".
16:09:58.662 warning "babel-jest > babel-preset-jest@26.6.2" has unmet peer dependency "@babel/core@^7.0.0".
16:09:58.662 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax@1.0.1" has unmet peer dependency "@babel/core@^7.0.0".
16:09:58.662 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax > @babel/plugin-syntax-async-generators@7.8.4" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.663 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax > @babel/plugin-syntax-bigint@7.8.3" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.663 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax > @babel/plugin-syntax-class-properties@7.12.1" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.663 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax > @babel/plugin-syntax-import-meta@7.10.4" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.663 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax > @babel/plugin-syntax-json-strings@7.8.3" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.663 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax > @babel/plugin-syntax-logical-assignment-operators@7.10.4" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.663 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax > @babel/plugin-syntax-nullish-coalescing-operator@7.8.3" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.663 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax > @babel/plugin-syntax-numeric-separator@7.10.4" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.663 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax > @babel/plugin-syntax-object-rest-spread@7.8.3" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.663 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax > @babel/plugin-syntax-optional-catch-binding@7.8.3" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.664 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax > @babel/plugin-syntax-optional-chaining@7.8.3" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.664 warning "babel-jest > babel-preset-jest > babel-preset-current-node-syntax > @babel/plugin-syntax-top-level-await@7.12.1" has unmet peer dependency "@babel/core@^7.0.0-0".
16:09:58.665 warning " > sass-loader@10.1.0" has unmet peer dependency "webpack@^4.36.0 || ^5.0.0".
16:09:58.665 warning " > vue-jest@3.0.7" has unmet peer dependency "vue@^2.x".
16:09:58.665 warning " > vue-jest@3.0.7" has unmet peer dependency "vue-template-compiler@^2.x".
16:09:58.665 warning " > @fortawesome/vue-fontawesome@2.0.2" has unmet peer dependency "@fortawesome/fontawesome-svg-core@>= 1.2.0 < 1.3".
16:09:58.666 warning " > @fortawesome/vue-fontawesome@2.0.2" has unmet peer dependency "vue@~2".
16:09:58.666 warning " > @nuxtjs/apollo@4.0.1-rc.5" has unmet peer dependency "apollo-cache-inmemory@^1.6.6".
16:09:58.666 warning "@nuxtjs/apollo > vue-apollo@3.0.5" has unmet peer dependency "apollo-client@^2.0.0".
16:09:58.666 warning "@nuxtjs/apollo > vue-apollo@3.0.5" has unmet peer dependency "apollo-link@^1.0.0".
16:09:58.667 warning "@nuxtjs/apollo > vue-cli-plugin-apollo > apollo-link-persisted-queries@0.2.2" has incorrect peer dependency "graphql@^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0".
16:09:58.668 warning "@nuxtjs/apollo > vue-cli-plugin-apollo > graphql-subscriptions@1.1.0" has incorrect peer dependency "graphql@^0.10.5 || ^0.11.3 || ^0.12.0 || ^0.13.0 || ^14.0.0".
16:09:58.676 warning "@nuxtjs/apollo > vue-cli-plugin-apollo > apollo > apollo-language-server > @apollographql/graphql-language-service-interface@2.0.2" has incorrect peer dependency "graphql@^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0".
16:09:58.678 warning "@nuxtjs/apollo > vue-cli-plugin-apollo > apollo-server-express > apollo-server-core > graphql-upload@8.1.0" has incorrect peer dependency "graphql@0.13.1 - 14".
16:09:58.678 warning "@nuxtjs/apollo > vue-cli-plugin-apollo > graphql-tools > @graphql-tools/graphql-tag-pluck > @vue/compiler-sfc@3.0.5" has unmet peer dependency "vue@3.0.5".
16:09:58.679 warning "@nuxtjs/apollo > vue-cli-plugin-apollo > apollo > apollo-language-server > @apollographql/graphql-language-service-interface > @apollographql/graphql-language-service-parser@2.0.2" has incorrect peer dependency "graphql@^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0".
16:09:58.679 warning "@nuxtjs/apollo > vue-cli-plugin-apollo > apollo > apollo-language-server > @apollographql/graphql-language-service-interface > @apollographql/graphql-language-service-types@2.0.2" has incorrect peer dependency "graphql@^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0".
16:09:58.680 warning "@nuxtjs/apollo > vue-cli-plugin-apollo > apollo > apollo-language-server > @apollographql/graphql-language-service-interface > @apollographql/graphql-language-service-utils@2.0.2" has incorrect peer dependency "graphql@^0.12.0 || ^0.13.0 || ^14.0.0".
16:09:58.683 warning "@nuxtjs/fontawesome > @fortawesome/vue-fontawesome@0.1.10" has unmet peer dependency "vue@~2".
16:09:58.683 warning " > bootstrap@4.5.3" has unmet peer dependency "popper.js@^1.16.1".
16:09:58.683 warning "bootstrap-vue > portal-vue@2.1.7" has unmet peer dependency "vue@^2.5.18".
16:10:21.514 [4/5] Building fresh packages...
16:10:24.311 [5/5] Cleaning modules...
16:10:31.512 Done in 68.14s.
16:10:31.549 [info] Install devDependencies took: 68485.85781 ms
16:10:31.549 [log] ----------------- Nuxt build -----------------
16:10:31.589 [log] Running nuxt build --standalone --no-lock --config-file "nuxt.config.js"
16:10:58.937 [error] [BABEL] Note: The code generator has deoptimised the styling of /vercel/workpath0/node_modules_dev/bootstrap-vue/src/icons/icons.js as it exceeds the max of 500KB.
16:11:27.729 [error] [BABEL] Note: The code generator has deoptimised the styling of /vercel/workpath0/node_modules_dev/bootstrap-vue/src/icons/icons.js as it exceeds the max of 500KB.
16:11:45.878 [info] Nuxt build took: 74328.587751 ms
16:11:45.878 [log] ----------------- Install dependencies -----------------
16:11:45.879 [log] Using cached node_modules_prod
16:11:46.182 yarn install v1.22.4
16:11:46.307 [1/5] Resolving packages...
16:11:47.454 [2/5] Fetching packages...
16:11:47.514 [3/5] Linking dependencies...
16:11:48.452 [4/5] Building fresh packages...
16:11:48.453 [5/5] Cleaning modules...
16:11:48.652 Done in 2.48s.
16:11:48.669 [info] Install dependencies took: 2790.274451 ms
16:11:48.669 [log] ----------------- Collect artifacts -----------------
16:11:50.551 [info] Collect artifacts took: 1882.117579 ms
16:11:51.702 Uploading build outputs...
16:11:58.395 Build completed. Populating build cache...
16:12:02.826 [log] ----------------- Collect cache -----------------
16:12:17.757 [info] 158 files collected from .nuxt
16:12:36.716 [info] 54504 files collected from .vercel_cache
16:12:55.182 [info] 50899 files collected from node_modules_dev
16:13:10.348 [info] 923 files collected from node_modules_prod
16:13:10.349 [info] Collect cache took: 67522.360394 ms
16:14:06.760 Uploading build cache [203.63 MB]...
16:14:13.964 Build cache uploaded: 7203.428ms
16:14:13.998 Done with "nuxt.config.js"

My package.json:

{
"name": "enabl-nuxt",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .",
"lint": "npm run lint:js",
"test": "jest"
},
"dependencies": {},
"devDependencies": {
"@nuxtjs/dotenv": "^1.4.1",
"@nuxtjs/eslint-config": "^3.1.0",
"@nuxtjs/eslint-module": "^2.0.0",
"@vue/test-utils": "^1.1.0",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.5.0",
"eslint": "^7.10.0",
"eslint-config-prettier": "^6.12.0",
"eslint-legacy": "npm:eslint@^6.8.0",
"eslint-plugin-nuxt": "^1.0.0",
"eslint-plugin-prettier": "^3.1.4",
"fibers": "^5.0.0",
"jest": "^26.5.0",
"prettier": "^2.1.2",
"pug": "^3.0.0",
"pug-plain-loader": "^1.1.0",
"sass": "^1.30.0",
"sass-loader": "^10.1.0",
"typescript": "^3.8.3",
"vue-jest": "^3.0.4",
"webpack-bundle-analyzer": "^4.3.0",
"@fortawesome/free-brands-svg-icons": "^5.15.1",
"@fortawesome/free-regular-svg-icons": "^5.15.1",
"@fortawesome/free-solid-svg-icons": "^5.15.1",
"@fortawesome/vue-fontawesome": "^2.0.2",
"@nuxtjs/apollo": "^4.0.1-rc.5",
"@nuxtjs/axios": "^5.12.4",
"@nuxtjs/fontawesome": "^1.1.2",
"@nuxtjs/proxy": "^2.1.0",
"@nuxtjs/vercel-builder": "^0.18.1",
"@vue/cli-shared-utils": "^4.5.9",
"bootstrap": "^4.5.2",
"bootstrap-vue": "^2.17.3",
"core-js": "^3.6.5",
"graphql": "^15.4.0",
"graphql-legacy": "npm:graphql@^14.5.8",
"graphql-tag": "^2.11.0",
"jquery": "^3.5.1",
"lazysizes": "^5.3.0-beta1",
"npm": "^6.14.10",
"nuxt": "^2.14.6",
"nuxt-i18n": "^6.16.0",
"vue-lazy-hydration": "^2.0.0-beta.4"
}
}

When I run it locally it does work..
Do you know what I am missing?

Collapse
heyshadowsmith profile image
Shadow Smith

I never thought about how all dependencies for Nuxt apps deployed to Vercel are dev dependencies, but it makes 100% sense. I appreciate this article, and I'm going to install all dependencies as dev moving forward.

Thanks!

Collapse
hoer profile image
hoer

You saved my day!
Congratulations, greetings from Brazil.

Collapse
chimchim2 profile image
Chim

This was super helpful while deploying my first SSR Nuxt app to Vercel. Followed your instructions and it worked first try w/o issue.

Domo!