Deployment
General Guidelines
If you are using Vue CLI along with a backend framework that handles static assets as part of its deployment, all you need to do is make sure Vue CLI generates the built files in the correct location, and then follow the deployment instruction of your backend framework.
If you are developing your frontend app separately from your backend - i.e. your backend exposes an API for your frontend to talk to, then your frontend is essentially a purely static app. You can deploy the built content in the dist
directory to any static file server, but make sure to set the correct publicPath.
Previewing Locally
The dist
directory is meant to be served by an HTTP server (unless you've configured publicPath
to be a relative value), so it will not work if you open dist/index.html
directly over file://
protocol. The easiest way to preview your production build locally is using a Node.js static file server, for example serve:
npm install -g serve
# -s flag means serve it in Single-Page Application mode
# which deals with the routing problem below
serve -s dist
history.pushState
Routing with If you are using Vue Router in history
mode, a simple static file server will fail. For example, if you used Vue Router with a route for /todos/42
, the dev server has been configured to respond to localhost:3000/todos/42
properly, but a simple static server serving a production build will respond with a 404 instead.
To fix that, you will need to configure your production server to fallback to index.html
for any requests that do not match a static file. The Vue Router docs provides configuration instructions for common server setups.
CORS
If your static frontend is deployed to a different domain from your backend API, you will need to properly configure CORS.
PWA
If you are using the PWA plugin, your app must be served over HTTPS so that Service Worker can be properly registered.
Platform Guides
GitHub Pages
Pushing updates manually
Set correct
publicPath
invue.config.js
.If you are deploying to
https://<USERNAME>.github.io/
, you can omitpublicPath
as it defaults to"/"
.If you are deploying to
https://<USERNAME>.github.io/<REPO>/
, (i.e. your repository is athttps://github.com/<USERNAME>/<REPO>
), setpublicPath
to"/<REPO>/"
. For example, if your repo name is "my-project", yourvue.config.js
should look like this:module.exports = { publicPath: process.env.NODE_ENV === 'production' ? '/my-project/' : '/' }
Inside your project, create
deploy.sh
with the following content (with highlighted lines uncommented appropriately) and run it to deploy:#!/usr/bin/env sh # abort on errors set -e # build npm run build # navigate into the build output directory cd dist # if you are deploying to a custom domain # echo 'www.example.com' > CNAME git init git add -A git commit -m 'deploy' # if you are deploying to https://<USERNAME>.github.io # git push -f git@github.com:<USERNAME>/<USERNAME>.github.io.git master # if you are deploying to https://<USERNAME>.github.io/<REPO> # git push -f git@github.com:<USERNAME>/<REPO>.git master:gh-pages cd -
Using Travis CI for automatic updates
Set correct
publicPath
invue.config.js
as explained above.Install the Travis CLI client:
gem install travis && travis --login
Generate a GitHub access token with repo permissions.
Grant the Travis job access to your repository:
travis set GITHUB_TOKEN=xxx
(xxx
is the personal access token from step 3.)Create a
.travis.yml
file in the root of your project.language: node_js node_js: - "node" cache: npm script: npm run build deploy: provider: pages skip_cleanup: true github_token: $GITHUB_TOKEN local_dir: dist on: branch: master
Push the
.travis.yml
file to your repository to trigger the first build.
GitLab Pages
As described by GitLab Pages documentation, everything happens with a .gitlab-ci.yml
file placed in the root of your repository. This working example will get you started:
# .gitlab-ci.yml file to be placed in the root of your repository
pages: # the job must be named pages
image: node:latest
stage: deploy
script:
- npm ci
- npm run build
- mv public public-vue # GitLab Pages hooks on the public folder
- mv dist public # rename the dist folder (result of npm run build)
artifacts:
paths:
- public # artifact path must be /public for GitLab Pages to pick it up
only:
- master
Typically, your static website will be hosted on https://yourUserName.gitlab.io/yourProjectName, so you will also want to create an initial vue.config.js
file to update the BASE_URL
value to match:
// vue.config.js file to be place in the root of your repository
// make sure you update `yourProjectName` with the name of your GitLab project
module.exports = {
publicPath: process.env.NODE_ENV === 'production'
? '/yourProjectName/'
: '/'
}
Please read through the docs on GitLab Pages domains for more info about the URL where your project website will be hosted. Be aware you can also use a custom domain.
Commit both the .gitlab-ci.yml
and vue.config.js
files before pushing to your repository. A GitLab CI pipeline will be triggered: when successful, visit your project's Settings > Pages
to see your website link, and click on it.
Netlify
On Netlify, setup up a new project from GitHub with the following settings:
- Build Command:
npm run build
oryarn build
- Publish directory:
dist
- Build Command:
Hit the deploy button!
Also checkout vue-cli-plugin-netlify-lambda.
In order to receive direct hits using history mode
on Vue Router, you need to create a file called _redirects
under /public
with the following content:
# Netlify settings for single-page application
/* /index.html 200
More information on Netlify redirects documentation.
Render
Render offers free static site hosting with fully managed SSL, a global CDN and continuous auto deploys from GitHub.
Create a new Web Service on Render, and give Render’s GitHub app permission to access your Vue repo.
Use the following values during creation:
- Environment:
Static Site
- Build Command:
npm run build
oryarn build
- Publish directory:
dist
- Environment:
That’s it! Your app will be live on your Render URL as soon as the build finishes.
In order to receive direct hits using history mode on Vue Router, you need to add the following rewrite rule in the Redirects/Rewrites
tab for your site.
- Source:
/*
- Destination:
/index.html
- Status
Rewrite
Learn more about setting up redirects, rewrites and custom domains on Render.
Amazon S3
Firebase
Create a new Firebase project on your Firebase console. Please refer to this documentation on how to setup your project.
Make sure you have installed firebase-tools globally:
npm install -g firebase-tools
From the root of your project, initialize firebase
using the command:
firebase init
Firebase will ask some questions on how to setup your project.
- Choose which Firebase CLI features you want to setup your project. Make sure to select
hosting
. - Select the default Firebase project for your project.
- Set your
public
directory todist
(or where your build's output is) which will be uploaded to Firebase Hosting.
// firebase.json
{
"hosting": {
"public": "dist"
}
}
- Select
yes
to configure your project as a single-page app. This will create anindex.html
and on yourdist
folder and configure yourhosting
information.
// firebase.json
{
"hosting": {
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
Run npm run build
to build your project.
To deploy your project on Firebase Hosting, run the command:
firebase deploy --only hosting
If you want other Firebase CLI features you use on your project to be deployed, run firebase deploy
without the --only
option.
You can now access your project on https://<YOUR-PROJECT-ID>.firebaseapp.com
.
Please refer to the Firebase Documentation for more details.
ZEIT Now
ZEIT Now is a cloud platform for websites and serverless APIs, that you can use to deploy your Vue projects to your personal domain (or a free .now.sh
suffixed URL).
This guide will show you how to get started in a few quick steps:
Step 1: Installing Now CLI
To install their command-line interface with npm, run the following command:
npm install -g now
Step 2: Deploying
You can deploy your application by running the following command in the root of the project directory:
now
Alternatively, you can also use their integration for GitHub or GitLab.
That’s all!
Your site will deploy, and you will receive a link similar to the following: https://vue.now-examples.now.sh
Out of the box, you are already provided with the necessary routes for rewriting requests (except for custom static files) directly to your index.html
file and the appropiate default caching headers. This behaviour can be overwritten like this.
Stdlib
TODO | Open to contribution.
Heroku
Create a
static.json
file:
{
"root": "dist",
"clean_urls": true,
"routes": {
"/**": "index.html"
}
}
- Add
static.json
file to git
git add static.json
git commit -m "add static configuration"
- Deploy to Heroku
heroku login
heroku create
heroku buildpacks:add heroku/nodejs
heroku buildpacks:add https://github.com/heroku/heroku-buildpack-static
git push heroku master
More info: https://gist.github.com/hone/24b06869b4c1eca701f9
Surge
To deploy with Surge the steps are very straightforward.
First you would need to build your project by running npm run build
. And if you haven't installed Surge's command line tool, you can simply do so by running the command:
npm install --global surge
Then cd into the dist/
folder of your project and then run surge
and follow the screen prompt. It will ask you to set up email and password if it is the first time you are using Surge. Confirm the project folder and type in your preferred domain and watch your project being deployed such as below.
project: /Users/user/Documents/myawesomeproject/dist/
domain: myawesomeproject.surge.sh
upload: [====================] 100% eta: 0.0s (31 files, 494256 bytes)
CDN: [====================] 100%
IP: **.**.***.***
Success! - Published to myawesomeproject.surge.sh
Verify your project is successfully published by Surge by visiting myawesomeproject.surge.sh
, vola! For more setup details such as custom domains, you can visit Surge's help page.
Bitbucket Cloud
As described in the Bitbucket documentation you need to create a repository named exactly
<USERNAME>.bitbucket.io
.It is possible to publish to a subfolder of the main repository, for instance if you want to have multiple websites. In that case set correct
publicPath
invue.config.js
.If you are deploying to
https://<USERNAME>.bitbucket.io/
, you can omitpublicPath
as it defaults to"/"
.If you are deploying to
https://<USERNAME>.bitbucket.io/<SUBFOLDER>/
, setpublicPath
to"/<SUBFOLDER>/"
. In this case the directory structure of the repository should reflect the url structure, for instance the repository should have a/<SUBFOLDER>
directory.Inside your project, create
deploy.sh
with the following content and run it to deploy:#!/usr/bin/env sh # abort on errors set -e # build npm run build # navigate into the build output directory cd dist git init git add -A git commit -m 'deploy' git push -f git@bitbucket.org:<USERNAME>/<USERNAME>.bitbucket.io.git master cd -
Docker (Nginx)
Deploy your application using nginx inside of a docker container.
Install docker
Create a
Dockerfile
file in the root of your project.FROM node:latest as build-stage WORKDIR /app COPY package*.json ./ RUN npm install COPY ./ . RUN npm run build FROM nginx as production-stage RUN mkdir /app COPY --from=build-stage /app/dist /app COPY nginx.conf /etc/nginx/nginx.conf
Create a
.dockerignore
file in the root of your projectSetting up the
.dockerignore
file preventsnode_modules
and any intermediate build artifacts from being copied to the image which can cause issues during building.**/node_modules **/dist
Create a
nginx.conf
file in the root of your projectNginx
is an HTTP(s) server that will run in your docker container. It uses a configuration file to determine how to serve content/which ports to listen on/etc. See the nginx configuration documentation for an example of all of the possible configuration options.The following is a simple
nginx
configuration that serves your vue project on port80
. The rootindex.html
is served forpage not found
/404
errors which allows us to usepushState()
based routing.user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root /app; index index.html; try_files $uri $uri/ /index.html; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } }
Build your docker image
docker build . -t my-app # Sending build context to Docker daemon 884.7kB # ... # Successfully built 4b00e5ee82ae # Successfully tagged my-app:latest
Run your docker image
This build is based on the official
nginx
image so log redirection has already been set up and self daemonizing has been turned off. Some other default settings have been setup to improve running nginx in a docker container. See the nginx docker repo for more info.docker run -d -p 8080:80 my-app curl localhost:8080 # <!DOCTYPE html><html lang=en>...</html>