This package attempts to provide a core set of functionality for Vue SSR apps, including a single point of update for as many related dependencies as possible.
- 2 Webpack builds for Vue SSR
- Client build
- Server build
- Base
entry-client.js
logic - Base
entry-server.js
logic - Express middleware for rendering using the client manifest and server bundle
- Logic for including Webpack HMR for the client bundle and middleware
eslint@4.19.1
jest@23.1.0
vue@2.5.16
vue-loader@15.2.4
vue-server-renderer@2.5.16
webpack@4.10.2
At one point in time, I found myself maintaining 3 or 4 separate Vue SSR apps. All of which had stemmed from the same basic approach documented in Vue's Official SSR Guide. However, the process of maintaining multiple separate apps was complicated for multiple reasons:
- When a new version of any Vue-related dependency was released, manual updates were required in each app:
- This included production dependencies, such as
vue
orvue-server-renderer
- But it also meant all development dependencies, such as
vue-loader
,babel-loader
,sass-loader
, etc.
- This included production dependencies, such as
- Beyond that, all of the apps were being linted and unit tested in the same ways, so whenever those underlying frameworks were updated, it again required duplicate updates across multiple apps:
eslint
,jest
,eslint-plugin-vue
,jest-serializer-vue
, etc.
- Often, while working in a single app, a new approach would occur to me that would enhance the logic being used for the core Vue SSR approach within the app. This change would then need to be ported to each of the other apps
- Build adjustments (base, client, server, or middleware)
- Adjustments to the
fetchData
approach - Dynamic vuex module support
- Routing logic alterations
Needless to say, all of that was tedious, time consuming, and annoying.
The primary goals of this library are:
- Provide a baseline webpack setup for a Vue SSR app
- Provide the baseline implementation of a Vue SSR app, limited to client/server entry points and base Vue SSR HTML rendering
- This includes HMR support if desired by the client
- Provide customization points to extend both of the above areas as needed
- Provide a single set of compatible
devDependencies
packaged together such that the client app can just includevue-ssr-build
as adevDependency
- Note that
vue
andvue-server-renderer
arepeerDependencies
so they will need to be included asdependencies
appropriately
- Note that
The following are currently non-goals of this repository:
- Provide any baseline components, layout, or themeing logic for your app. You are expected the build the Component-based app in it's entirety, and provide a
createApp
function tovue-ssr-build
- Provide a server implementation. You are expected to create youe own
express
server and use the renderer middleware provided by this repo. - Providing any build execution scripts. You will be required to setup all of your scripts/tasks to build and run your app
- Provide any CLI or scaffolding support for your app. This will likely include a small
demo
folder which will show an example of how to usevue-ssr-build
, but at the moment you will be required to copy or mimic those files in your app
// build/webpack.client.config.js
const { join } = require('path');
const merge = require('webpack-merge');
const getClientConfig = require('vue-ssr-build/build/webpack.client.config');
// Configuration options that can be passed to getClientConfig
const configOpts = {
type: 'client', // required (client|server)
rootDir: null, // required - root directory of the repo,
// used for aliases
i18nBlocks: false, // Boolean - include support for <i18n> blocks
// in components
theme: null, // Theme for vue-themed-style-loader
sassLoaderData: null, // Data to pass to sass-loader
};
module.exports = merge(getClientConfig(configOpts), {
// Additional customizations here
});
// build/webpack.server.config.js
const { join } = require('path');
const merge = require('webpack-merge');
const getServerConfig = require('vue-ssr-build/build/webpack.server.config');
// Configuration options that can be passed to getServerConfig
const configOpts = {
type: 'client', // required (client|server)
rootDir: null, // required - root directory of the repo,
// used for aliases
i18nBlocks: false, // Boolean - include support for <i18n> blocks
// in components
theme: null, // Theme for vue-themed-style-loader
sassLoaderData: null, // Data to pass to sass-loader
};
module.exports = merge(getServerConfig(configOpts), {
// Additional customizations here
});
import initializeClient from 'vue-ssr-build/src/entry-client';
import createApp from './path/to/your/create/app';
initializeClient(createApp, {
// The following are all available options and their default values:
// selector for where to mount the app
appSelector: '#app',
// Include HMR support?
hmr: true,
// Any existing initial vuex state, otherwise
initialState: null,
// Name of the meta tag where state is stringified
initialStateMetaTag: 'initial-state',
// Wire up logic for route-level vuex modules?
vuexModules: true,
// Logger instance
logger: console
});
import initializeServer from 'vue-ssr-build/src/entry-server';
import createApp from '@js/create-app';
export default initializeServer(createApp, {
// The following are all available options and their default values:
// Wire up logic for route-level vuex modules?
vuexModules: true,
// Provide a function which will return a promise of all initial
// i18n translations to be included
i18nLoader: null,
// Logger instance
logger: console
});
const express = require('express');
const app = express();
const rootPath = path.join(__dirname, '../..');
app.use('*', vueRenderer(app, {
// The following are all available options and their default values:
// Local build
isLocal: process.env.NODE_ENV === 'local',
// Dev build
isDev: process.env.NODE_ENV === 'development',
// Prod build
isProd: process.env.NODE_ENV === 'production',
// Enable HMR?
hmr: false,
// Additional options to pass to createBundleRenderer
rendererOpts: null,
// The remaining must be specified as absolute paths:
templatePath: path.join(rootDir, 'src/index.tpl.html'),
clientConfig: path.join(rootDir, 'build/webpack.client.config.js'),
serverConfig: path.join(rootDir, 'build/webpack.server.config.js'),
clientManifest: path.join(rootDir, 'dist/vue-ssr-client-manifest.json'),
serverBundle: path.join(rootDir, 'dist/vue-ssr-server-bundle.json'),
}));
For ease of use, this repository also provides .babelrc.js
, .eslintrc.js
and jest.config.js
files that should work with the default configurations. Simply import them into your configs an extend as needed.
This repository assumes a default folder structure and sets up webpack aliases and jest resolvers accordingly. This can be overrideen in your own configurations.
YourRepo/
build/
## Webpack configs here
dist/ (alias @dist)
## Webpack should write output here
src/
components/ (alias @components)
js/ (alias @js)
scss/ (alias @scss)
server/ (alias @server)
store/ (alias @store)
static/ (alias @static)
## Static files (favicon.ico, etc.)