Skip to content

Commit

Permalink
feat: expose env variables as root level in index.html template
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed May 8, 2018
1 parent 2dcdedd commit 4c5784d
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 10 deletions.
14 changes: 14 additions & 0 deletions docs/env.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ In addition to `VUE_APP_*` variables, there are also two special variables that
- `NODE_ENV` - this will be one of `"development"`, `"production"` or `"test"` depending on the [mode](#modes) the app is running in.
- `BASE_URL` - this corresponds to the `baseUrl` option in `vue.config.js` and is the base path your app is deployed at.

### Env Variables in Index HTML

All resolved env variables will be available inside `public/index.html` via [lodash template interpolation](https://lodash.com/docs/4.17.5#template):

- `<%= VAR %>` for unescaped interpolation;
- `<%- VAR %>` for HTML-escaped interpolationl;
- `<% expression %>` for JavaScript control flows.

For example, to reference static assets copied from the root of `public`, you will need to use the `BASE_URL` variable:

``` html
<link rel="shortcut icon" href="<%= BASE_URL %>favicon.ico">
```

### Local Only Variables

Sometimes you might have env variables that should not be committed into the codebase, especially if your project is hosted in a public repository. In that case you should use an `.env.local` file instead. Local env files are ignored in `.gitignore` by default.
Expand Down
3 changes: 3 additions & 0 deletions packages/@vue/cli-service/__tests__/build.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ test('build', async () => {
// should preload css
expect(index).toMatch(/<link [^>]+app[^>]+\.css rel=preload>/)

// should reference favicon with correct base URL
expect(index).toMatch(/<link rel=icon href=\/favicon.ico>/)

const port = await portfinder.getPortPromise()
server = createServer({ root: path.join(project.dir, 'dist') })

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="shortcut icon" href="<%%= webpackConfig.output.publicPath %%>favicon.ico">
<link rel="icon" href="<%%= BASE_URL %%>favicon.ico">
<title><%= rootOptions.projectName %></title>
</head>
<body>
Expand Down
34 changes: 25 additions & 9 deletions packages/@vue/cli-service/lib/config/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,34 @@ module.exports = (api, options) => {
}

// HTML plugin
const fs = require('fs')
const htmlPath = api.resolve('public/index.html')
const resolveClientEnv = require('../util/resolveClientEnv')
const htmlOptions = {
templateParameters: (compilation, assets, pluginOptions) => {
// enhance html-webpack-plugin's built in template params
let stats
return Object.assign({
// make stats lazy as it is expensive
get webpack () {
return stats || (stats = compilation.getStats().toJson())
},
compilation: compilation,
webpackConfig: compilation.options,
htmlWebpackPlugin: {
files: assets,
options: pluginOptions
}
}, resolveClientEnv(options.baseUrl, true /* raw */))
}
}
// only set template path if index.html exists
const htmlPath = api.resolve('public/index.html')
if (require('fs').existsSync(htmlPath)) {
htmlOptions.template = htmlPath
}

webpackConfig
.plugin('html')
.use(require('html-webpack-plugin'), [
Object.assign(
fs.existsSync(htmlPath) ? { template: htmlPath } : {},
// expose client env to html template
{ env: resolveClientEnv(options.baseUrl, true /* raw */) }
)
])
.use(require('html-webpack-plugin'), [htmlOptions])

// inject preload/prefetch to HTML
const PreloadPlugin = require('preload-webpack-plugin')
Expand Down

0 comments on commit 4c5784d

Please sign in to comment.