# Build Configuration We will assume you already know how to configure webpack for a client-only project. The config for an SSR project will be largely similar, but we suggest breaking the config into three files: *base*, *client* and *server*. The base config contains config shared for both environments, such as output path, aliases, and loaders. The server config and client config can simply extend the base config using [webpack-merge](https://github.com/survivejs/webpack-merge). ## Server Config The server config is meant for generating the server bundle that will be passed to `createBundleRenderer`. It should look like this: ``` js const merge = require('webpack-merge') const nodeExternals = require('webpack-node-externals') const baseConfig = require('./webpack.base.config.js') const VueSSRServerPlugin = require('vue-server-renderer/server-plugin') module.exports = merge(baseConfig, { // Point entry to your app's server entry file entry: '/path/to/entry-server.js', // This allows webpack to handle dynamic imports in a Node-appropriate // fashion, and also tells `vue-loader` to emit server-oriented code when // compiling Vue components. target: 'node', // For bundle renderer source map support devtool: 'source-map', // This tells the server bundle to use Node-style exports output: { libraryTarget: 'commonjs2' }, // https://webpack.js.org/configuration/externals/#function // https://github.com/liady/webpack-node-externals // Externalize app dependencies. This makes the server build much faster // and generates a smaller bundle file. externals: nodeExternals({ // do not externalize dependencies that need to be processed by webpack. // you can add more file types here e.g. raw *.vue files // you should also whitelist deps that modifies `global` (e.g. polyfills) whitelist: /\.css$/ }), // This is the plugin that turns the entire output of the server build // into a single JSON file. The default file name will be // `vue-ssr-server-bundle.json` plugins: [ new VueSSRServerPlugin() ] }) ``` After `vue-ssr-server-bundle.json` has been generated, simply pass the file path to `createBundleRenderer`: ``` js const { createBundleRenderer } = require('vue-server-renderer') const renderer = createBundleRenderer('/path/to/vue-ssr-server-bundle.json', { // ...other renderer options }) ``` Alternatively, you can also pass the bundle as an Object to `createBundleRenderer`. This is useful for hot-reload during development - see the HackerNews demo for a [reference setup](https://github.com/vuejs/vue-hackernews-2.0/blob/master/build/setup-dev-server.js). ### Externals Caveats Notice that in the `externals` option we are whitelisting CSS files. This is because CSS imported from dependencies should still be handled by webpack. If you are importing any other types of files that also rely on webpack (e.g. `*.vue`, `*.sass`), you should add them to the whitelist as well. If you are using `runInNewContext: 'once'` or `runInNewContext: true`, then you also need to whitelist polyfills that modify `global`, e.g. `babel-polyfill`. This is because when using the new context mode, **code inside a server bundle has its own `global` object.** Since you don't really need it on the server when using Node 7.6+, it's actually easier to just import it in the client entry. ## Client Config The client config can remain largely the same with the base config. Obviously you need to point `entry` to your client entry file. Aside from that, if you are using `CommonsChunkPlugin`, make sure to use it only in the client config because the server bundle requires a single entry chunk. ### Generating `clientManifest` > requires version 2.3.0+ In addition to the server bundle, we can also generate a client build manifest. With the client manifest and the server bundle, the renderer now has information of both the server *and* client builds, so it can automatically infer and inject [preload / prefetch directives](https://css-tricks.com/prefetching-preloading-prebrowsing/) and css links / script tags into the rendered HTML. The benefits is two-fold: 1. It can replace `html-webpack-plugin` for injecting the correct asset URLs when there are hashes in your generated filenames. 2. When rendering a bundle that leverages webpack's on-demand code splitting features, we can ensure the optimal chunks are preloaded / prefetched, and also intelligently inject ` ` ``` ### Manual Asset Injection By default, asset injection is automatic when you provide the `template` render option. But sometimes you might want finer-grained control over how assets are injected into the template, or maybe you are not using a template at all. In such a case, you can pass `inject: false` when creating the renderer and manually perform asset injection. In the `renderToString` callback, the `context` object you passed in will expose the following methods: - `context.renderStyles()` This will return inline `