Using Vue SPA (created with webpack) in subfolder

There is a common use case where Vue SPA will run in some subfolder in production environment.

When you develop Vue app using Vue-cli all your links are targeting root folder. There are some topics on Vue forums about that problem but there are not complete, so here is a solution that works. I am not saying that it is the best or. only possible, but it works!

Solution:

I am using two index.html files. One for development (index.html) and the other for production (index_prod.html). Files are 95% the same, except some minor changes in index_prod.html. So, if this is basic index.html

<!DOCTYPE html>
<html>
  <head>
    <metacharset="utf-8">
    <metaname="viewport" content="width=device-width,initial-scale=1.0">
  </head>

  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <script src="/static/config.js"></script>
  </body>
</html>

For production you must use base tag and change src link (if you need one!)

<!DOCTYPE html>
<html>
  <head>
    <basehref="/sub-folder/" />
    <metacharset="utf-8">
    <metaname="viewport" content="width=device-width,initial-scale=1.0">
  </head>
  
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <script src="/sub-folder/static/config.js"></script>
  </body>
</html>

Because I am using index_prod for production I must inform webpack about that. So, I need to change webpack.prod.config.js, by adding template property to HtmlWebpackPlugin:
newHtmlWebpackPlugin({
  filename: config.build.index,
  template: 'index_prod.html',
  inject: true,
  ...

Next, I must inform webpack to use new public path, so I must again change webpack.prod.config.js, by adding publicPath property to webpackConfig.output:
output: {
  path: config.build.assetsRoot,
  publicPath: '/sub-folder/',
  filename:utils.assetsPath('js/[name].[chunkhash].js'),
  chunkFilename:utils.assetsPath('js/[id].[chunkhash].js')
},

Then I must inform router to use new public path, so I must add base property to router object
let router = new Router({
  routes: […]
  base: ‘/sub-folder/’,
  mode: ‘history’
})
And that’s it! Now I can copy DIST folder to /sub-folder/ on production.

Tags: ,

Leave a Reply

You must be logged in to post a comment.