Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --inline-vue flag for build command to avoid externalization of Vue in lib & wc mode #4261

Merged
merged 5 commits into from
Aug 19, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/guide/build-targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ App is the default build target. In this mode:

::: tip Note on Vue Dependency
In lib mode, Vue is *externalized*. This means the bundle will not bundle Vue even if your code imports Vue. If the lib is used via a bundler, it will attempt to load Vue as a dependency through the bundler; otherwise, it falls back to a global `Vue` variable.

To avoid this behavior provide `--inline-vue` flag to `build` command.

```
vue-cli-service build --target lib --inline-vue -name myLib [entry]
```
:::

You can build a single entry as a library using
Expand Down Expand Up @@ -68,6 +74,8 @@ Web Component mode does not support IE11 and below. [More details](https://githu

::: tip Note on Vue Dependency
In web component mode, Vue is *externalized.* This means the bundle will not bundle Vue even if your code imports Vue. The bundle will assume `Vue` is available on the host page as a global variable.

To avoid this behavior provide `--inline-vue` flag to `build` command.
:::

You can build a single entry as a web component using
Expand Down
1 change: 1 addition & 0 deletions docs/guide/cli-service.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Options:
--modern build app targeting modern browsers with auto fallback
--target app | lib | wc | wc-async (default: app)
--formats list of output formats for library builds (default: commonjs,umd,umd-min)
--inline-vue include the Vue module in the final bundle of library or web component target
--name name for lib or web-component mode (default: "name" in package.json or entry filename)
--no-clean do not remove the dist directory before building the project
--report generate report.html to help analyze bundle content
Expand Down
8 changes: 8 additions & 0 deletions docs/ru/guide/build-targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@

::: tip Примечание о зависимости Vue
В режиме библиотеки Vue *экстернализируется*. Это означает, что сборка не будет содержать Vue, даже если ваш код его импортирует. Если библиотека используется через сборщик, он должен попытаться загрузить Vue в качестве зависимости через сборщик; в противном случае, он должен вернуться к глобальной переменной `Vue`.

Чтобы избежать экстернализиции Vue установите флаг `--inline-vue` для команды `build`.

```
vue-cli-service build --target lib --inline-vue -name myLib [entry]
```
:::

Вы можете запустить сборку одной точки входа в качестве библиотеки с помощью:
Expand Down Expand Up @@ -72,6 +78,8 @@ module.exports = {

::: tip Примечание зависимости Vue
В режиме веб-компонентов Vue *экстернализируется.* Это означает, что сборка не будет содержать Vue, даже если ваш код его импортирует. Сборка будет подразумевать, что `Vue` доступен на странице в качестве глобальной переменной.

Чтобы избежать экстернализиции Vue установите флаг `--inline-vue` для команды `build`.
:::

Вы можете запустить сборку одной точки входа в качестве веб-компонента с помощью:
Expand Down
1 change: 1 addition & 0 deletions docs/ru/guide/cli-service.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ npx vue-cli-service serve
--dest определить каталог сборки (по умолчанию: dist)
--modern собирать приложение для современных браузеров с авто-фоллбэком для старых
--target app | lib | wc | wc-async (по умолчанию: app)
--inline-vue включить Vue в содержимое сборки библиотеки или веб-компонента
--name имя библиотеки или режим веб-компонента (по умолчанию: "name" в package.json или имя файла точки входа)
--no-clean не удалять каталог dist перед сборкой проекта
--report сгенерировать report.html для анализа содержимого сборки
Expand Down
56 changes: 56 additions & 0 deletions packages/@vue/cli-service/__tests__/buildLib.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,59 @@ test('build as lib without --name and --filename options (default to package nam
expect(project.has('dist/test-lib.umd.js')).toBe(true)
expect(project.has('dist/test-lib.umd.min.js')).toBe(true)
})

test('build as lib with --inline-vue', async () => {
const project = await create('build-lib-inline-vue', defaultPreset)

await project.write('src/main-lib.js', `
import Vue from 'vue'
import App from "./components/App.vue"

document.addEventListener("DOMContentLoaded", function() {
new Vue({
render: h => h(App),
}).$mount('body');
});
`)

await project.write('src/components/App.vue', `
<template>
<div>{{ message }}<div>
</template>
<script>
export default {
data() {
return {
message: 'Hello from Lib'
}
},
}
</script>
`)

const { stdout } = await project.run('vue-cli-service build --target lib --inline-vue --name testLib src/main-lib.js')
expect(stdout).toMatch('Build complete.')

expect(project.has('dist/demo.html')).toBe(true)
expect(project.has('dist/testLib.common.js')).toBe(true)
expect(project.has('dist/testLib.umd.js')).toBe(true)
expect(project.has('dist/testLib.umd.min.js')).toBe(true)

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

await new Promise((resolve, reject) => {
server.listen(port, err => {
if (err) return reject(err)
resolve()
})
})

const launched = await launchPuppeteer(`http://localhost:${port}/demo.html`)
browser = launched.browser
page = launched.page
const divText = await page.evaluate(() => {
return document.querySelector('div').textContent
})
expect(divText).toMatch('Hello from Lib')
})
55 changes: 55 additions & 0 deletions packages/@vue/cli-service/__tests__/buildWc.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,61 @@ test('build as single wc', async () => {
expect(h1Text).toMatch('Welcome to Your Vue.js App')
})

test('build as wc with --inline-vue', async () => {
const project = await create('build-wc-inline-vue', defaultPreset)

await project.write('src/main-wc.js', `
import Vue from 'vue'
import App from "./components/App.vue"

document.addEventListener("DOMContentLoaded", function() {
new Vue({
render: h => h(App),
}).$mount('body');
});
`)

await project.write('src/components/App.vue', `
<template>
<div>{{ message }}<div>
</template>
<script>
export default {
data() {
return {
message: 'Hello from Wc'
}
},
}
</script>
`)

const { stdout } = await project.run('vue-cli-service build --target wc --inline-vue --name single-wc src/main-wc.js')
expect(stdout).toMatch('Build complete.')

expect(project.has('dist/demo.html')).toBe(true)
expect(project.has('dist/single-wc.js')).toBe(true)
expect(project.has('dist/single-wc.min.js')).toBe(true)

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

await new Promise((resolve, reject) => {
server.listen(port, err => {
if (err) return reject(err)
resolve()
})
})

const launched = await launchPuppeteer(`http://localhost:${port}/demo.html`)
browser = launched.browser
page = launched.page
const divText = await page.evaluate(() => {
return document.querySelector('div').textContent
})
expect(divText).toMatch('Hello from Wc')
})

afterEach(async () => {
if (browser) {
await browser.close()
Expand Down
1 change: 1 addition & 0 deletions packages/@vue/cli-service/bin/vue-cli-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const args = require('minimist')(rawArgv, {
'modern',
'report',
'report-json',
'inline-vue',
'watch',
// serve
'open',
Expand Down
1 change: 1 addition & 0 deletions packages/@vue/cli-service/lib/commands/build/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ module.exports = (api, options) => {
'--modern': `build app targeting modern browsers with auto fallback`,
'--no-unsafe-inline': `build app without introducing inline scripts`,
'--target': `app | lib | wc | wc-async (default: ${defaults.target})`,
'--inline-vue': 'include the Vue module in the final bundle of library or web component target',
'--formats': `list of output formats for library builds (default: ${defaults.formats})`,
'--name': `name for lib or web-component mode (default: "name" in package.json or entry filename)`,
'--filename': `file name for output, only usable for 'lib' target (default: value of --name)`,
Expand Down
14 changes: 8 additions & 6 deletions packages/@vue/cli-service/lib/commands/build/resolveLibConfig.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const fs = require('fs')
const path = require('path')

module.exports = (api, { entry, name, formats, filename }, options) => {
module.exports = (api, { entry, name, formats, filename, 'inline-vue': inlineVue }, options) => {
const { log, error } = require('@vue/cli-shared-utils')
const abort = msg => {
log()
Expand Down Expand Up @@ -97,11 +97,13 @@ module.exports = (api, { entry, name, formats, filename }, options) => {
rawConfig.externals = [
...(Array.isArray(rawConfig.externals) ? rawConfig.externals : [rawConfig.externals]),
{
vue: {
commonjs: 'vue',
commonjs2: 'vue',
root: 'Vue'
}
...(!inlineVue ? {
vue: {
commonjs: 'vue',
commonjs2: 'vue',
root: 'Vue'
}
} : {})
romansp marked this conversation as resolved.
Show resolved Hide resolved
}
].filter(Boolean)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const path = require('path')
const webpack = require('webpack')
const { resolveEntry, fileToComponentName } = require('./resolveWcEntry')

module.exports = (api, { target, entry, name }) => {
module.exports = (api, { target, entry, name, 'inline-vue': inlineVue }) => {
// Disable CSS extraction and turn on CSS shadow mode for vue-style-loader
process.env.VUE_CLI_CSS_SHADOW_MODE = true

Expand Down Expand Up @@ -100,7 +100,9 @@ module.exports = (api, { target, entry, name }) => {
rawConfig.externals = [
...(Array.isArray(rawConfig.externals) ? rawConfig.externals : [rawConfig.externals]),
{
vue: 'Vue'
...(!inlineVue ? {
vue: 'Vue'
} : {})
romansp marked this conversation as resolved.
Show resolved Hide resolved
}
].filter(Boolean)

Expand Down