Skip to content

Commit

Permalink
feat(nuxt-module): add tree-shaking support to Nuxt module (#2654)
Browse files Browse the repository at this point in the history
  • Loading branch information
pimlie authored and tmorehouse committed Feb 23, 2019
1 parent afbb650 commit 9aaf32f
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 44 deletions.
24 changes: 24 additions & 0 deletions docs/markdown/intro/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,30 @@ In your app main entry point include the single custom SCSS file (when using `sa
import 'custom.scss'
```

### Tree shaking with Nuxt.js

If you wish to reduce your bundle size because you only use a subset of the available
BootstrapVue plugins, you can configure the list of BootstrapVue
`componentPlugins` or `directivePlugins` you want to globally install in
your Nuxt.js project.

```js
{
modules: ['bootstrap-vue/nuxt'],
bootstrapVue: {
componentPlugins: [
'Form',
'FormCheckbox',
'FormInput',
'FormRadio'
],
directivePlugins: [
'Popover'
]
}
}
```

## Vue CLI 2

BootstrapVue has two Vue CLI templates available:
Expand Down
115 changes: 71 additions & 44 deletions nuxt/index.js
Original file line number Diff line number Diff line change
@@ -1,51 +1,78 @@
const { resolve } = require('path')

function pickFirst(...args) {
for (const arg of args) {
if (arg !== undefined) {
return arg
module.exports = function nuxtBootstrapVue(moduleOptions = {}) {
this.nuxt.hook('build:before', () => {
function pickFirst(...args) {
for (const arg of args) {
if (arg !== undefined) {
return arg
}
}
}
}
}

module.exports = function nuxtBootstrapVue(moduleOptions = {}) {
// Merge moduleOptions with default
const options = {
...this.options.bootstrapVue,
...moduleOptions
}

const bootstrapVueCSS = pickFirst(
options.bootstrapVueCSS,
options.bootstrapVueCss,
options.bvCSS,
// Defaults to `true` if no other options provided
true
)
if (bootstrapVueCSS) {
// Add BootstrapVue CSS
this.options.css.unshift('bootstrap-vue/dist/bootstrap-vue.css')
}

const bootstrapCSS = pickFirst(
options.bootstrapCSS,
options.bootstrapCss,
options.css,
// Defaults to `true` if no other options provided
true
)
if (bootstrapCSS) {
// Add Bootstrap CSS before BootstrapVue CSS
this.options.css.unshift('bootstrap/dist/css/bootstrap.css')
}

// Transpile src
this.options.build.transpile.push('bootstrap-vue/src')

// Register plugin, pasing options to plugin template
this.addPlugin({
src: resolve(__dirname, 'plugin.template.js'),
fileName: 'bootstrap-vue.js'
const kebabCase = str =>
str.replace(
/([_\s]+([a-zA-Z])|([A-Z]))/g,
(m, $1, $2, $3, o) => (o ? '-' : '') + ($2 || $3 || '').toLowerCase()
)
const pascalCase = str => str.replace(/(^|[-_\s]+)(.)/g, (m, $1, $2) => $2.toUpperCase())

// Merge moduleOptions with default
const options = {
...this.options.bootstrapVue,
...moduleOptions
}

const bootstrapVueCSS = pickFirst(
options.bootstrapVueCSS,
options.bootstrapVueCss,
options.bvCSS,
// Defaults to `true` if no other options provided
true
)
if (bootstrapVueCSS) {
// Add BootstrapVue CSS
this.options.css.unshift('bootstrap-vue/dist/bootstrap-vue.css')
}

const bootstrapCSS = pickFirst(
options.bootstrapCSS,
options.bootstrapCss,
options.css,
// Defaults to `true` if no other options provided
true
)
if (bootstrapCSS) {
// Add Bootstrap CSS
this.options.css.unshift('bootstrap/dist/css/bootstrap.css')
}

// Transpile src
this.options.build.transpile.push('bootstrap-vue/src')

const templateOptions = {}

// TODO: also add support for individual components & directives
for (const type of ['componentPlugins', 'directivePlugins']) {
const bvPlugins = Array.isArray(options[type]) ? options[type] : []

templateOptions[type] = bvPlugins
// convert everything to kebab
.map(p => kebabCase(p))
// remove duplicate items
.filter((p, i, arr) => arr.indexOf(p) === i)
.map(pluginDir => {
const moduleName = (type === 'directivePlugins' ? 'v' : '') + pascalCase(pluginDir)
return [moduleName, pluginDir]
})
}

// Register plugin, pasing options to plugin template
this.addPlugin({
src: resolve(__dirname, 'plugin.template.js'),
fileName: 'bootstrap-vue.js',
options: templateOptions
})
})
}

Expand Down
9 changes: 9 additions & 0 deletions nuxt/plugin.template.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import Vue from 'vue'
<% if (options.componentPlugins.length || options.directivePlugins.length) { %><%=
options.componentPlugins.reduce((acc, p) => (acc += `import ${p[0]} from 'bootstrap-vue/es/components/${p[1]}'\n` ), '') %><%=
options.directivePlugins.reduce((acc, p) => (acc += `import ${p[0]} from 'bootstrap-vue/es/directives/${p[1]}'\n` ), '') %>

<%=
options.componentPlugins.reduce((acc, p) => (acc += `Vue.use(${p[0]})\n` ), '') %><%=
options.directivePlugins.reduce((acc, p) => (acc += `Vue.use(${p[0]})\n` ), '') %>
<% } else { %>
import BootstrapVue from 'bootstrap-vue/es'

Vue.use(BootstrapVue)
<% } %>

0 comments on commit 9aaf32f

Please sign in to comment.