mirror of
https://github.com/vuejs/vue-cli.git
synced 2026-03-20 18:11:07 -05:00
feat(build): add --inline-vue flag to optionally disable externalization of Vue (#4261)
Resolves #4055.
This commit is contained in:
committed by
Haoqun Jiang
parent
497fd5aa1f
commit
86f4f5fceb
@@ -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
|
||||
```
|
||||
:::
|
||||
|
||||
You can build a single entry as a library using
|
||||
@@ -68,6 +74,12 @@ 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.
|
||||
|
||||
```
|
||||
vue-cli-service build --target wc --inline-vue
|
||||
```
|
||||
:::
|
||||
|
||||
You can build a single entry as a web component using
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -19,6 +19,12 @@
|
||||
|
||||
::: tip Примечание о зависимости Vue
|
||||
В режиме библиотеки Vue *экстернализируется*. Это означает, что сборка не будет содержать Vue, даже если ваш код его импортирует. Если библиотека используется через сборщик, он должен попытаться загрузить Vue в качестве зависимости через сборщик; в противном случае, он должен вернуться к глобальной переменной `Vue`.
|
||||
|
||||
Чтобы избежать экстернализиции Vue установите флаг `--inline-vue` для команды `build`.
|
||||
|
||||
```
|
||||
vue-cli-service build --target lib --inline-vue
|
||||
```
|
||||
:::
|
||||
|
||||
Вы можете запустить сборку одной точки входа в качестве библиотеки с помощью:
|
||||
@@ -72,6 +78,12 @@ module.exports = {
|
||||
|
||||
::: tip Примечание зависимости Vue
|
||||
В режиме веб-компонентов Vue *экстернализируется.* Это означает, что сборка не будет содержать Vue, даже если ваш код его импортирует. Сборка будет подразумевать, что `Vue` доступен на странице в качестве глобальной переменной.
|
||||
|
||||
Чтобы избежать экстернализиции Vue установите флаг `--inline-vue` для команды `build`.
|
||||
|
||||
```
|
||||
vue-cli-service build --target wc --inline-vue
|
||||
```
|
||||
:::
|
||||
|
||||
Вы можете запустить сборку одной точки входа в качестве веб-компонента с помощью:
|
||||
|
||||
@@ -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 для анализа содержимого сборки
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -22,6 +22,7 @@ const args = require('minimist')(rawArgv, {
|
||||
'modern',
|
||||
'report',
|
||||
'report-json',
|
||||
'inline-vue',
|
||||
'watch',
|
||||
// serve
|
||||
'open',
|
||||
|
||||
@@ -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)`,
|
||||
|
||||
@@ -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()
|
||||
@@ -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'
|
||||
}
|
||||
})
|
||||
}
|
||||
].filter(Boolean)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -99,9 +99,7 @@ module.exports = (api, { target, entry, name }) => {
|
||||
// externalize Vue in case user imports it
|
||||
rawConfig.externals = [
|
||||
...(Array.isArray(rawConfig.externals) ? rawConfig.externals : [rawConfig.externals]),
|
||||
{
|
||||
vue: 'Vue'
|
||||
}
|
||||
{ ...(inlineVue || { vue: 'Vue' }) }
|
||||
].filter(Boolean)
|
||||
|
||||
const entryName = `${libName}${minify ? `.min` : ``}`
|
||||
|
||||
Reference in New Issue
Block a user