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

fix: bundle dependencies inline and fix es build #116

Merged
merged 15 commits into from
May 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 3 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@
"README.md",
"dist/index.d.ts"
],
"dependencies": {
"dom-event-types": "^1.0.0",
"lodash": "^4.17.15"
},
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.8.4",
Expand All @@ -26,11 +22,12 @@
"@rollup/plugin-replace": "^2.3.2",
"@types/estree": "^0.0.42",
"@types/jest": "^24.9.1",
"@types/lodash": "^4.14.149",
"@types/node": "12.12.35",
"@vue/compiler-dom": "^3.0.0-beta.12",
"@vue/compiler-sfc": "^3.0.0-beta.12",
"babel-jest": "^25.2.3",
"babel-preset-jest": "^25.2.1",
"dom-event-types": "^1.0.0",
"flush-promises": "^1.0.2",
"husky": "^4.2.3",
"jest": "^25.1.0",
Expand All @@ -48,6 +45,7 @@
"vuex": "^4.0.0-beta.1"
},
"peerDependencies": {
"@vue/compiler-dom": "^3.0.0-beta.12",
"@vue/compiler-sfc": "^3.0.0-beta.12",
"vue": "^3.0.0-beta.12"
},
Expand Down
15 changes: 3 additions & 12 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ function createEntry(options) {
external: [
'vue',
'@vue/compiler-dom',
'lodash/mergeWith',
'lodash/isString'
],
plugins: [
replace({
Expand All @@ -43,30 +41,24 @@ function createEntry(options) {
globals: {
vue: 'Vue',
'@vue/compiler-dom': 'VueCompilerDOM',
'lodash/mergeWith': '_.mergeWith',
'lodash/isString': '_.isString',
}
}
}

if (['es', 'cjs'].includes(format)) {
config.external.push('dom-event-types')
}

if (format === 'es') {
config.output.file = isBrowser ? pkg.browser : pkg.module
config.output.file = pkg.module
}
if (format === 'cjs') {
config.output.file = pkg.main
}
console.log('file is', config.output.file)
console.log(`Building ${format}: ${config.output.file}`)

config.plugins.push(
ts({
check: format === 'es' && isBrowser,
tsconfigOverride: {
compilerOptions: {
declaration: format === 'es' && isBrowser,
declaration: format === 'es',
target: 'es5', // not sure what this should be?
module: format === 'cjs' ? 'es2015' : 'esnext'
},
Expand All @@ -80,7 +72,6 @@ function createEntry(options) {

export default [
createEntry({ format: 'es', input: 'src/index.ts', isBrowser: false }),
createEntry({ format: 'es', input: 'src/index.ts', isBrowser: true }),
createEntry({ format: 'iife', input: 'src/index.ts', isBrowser: true }),
createEntry({ format: 'cjs', input: 'src/index.ts', isBrowser: false }),
]
2 changes: 1 addition & 1 deletion src/create-dom-event.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as eventTypes from 'dom-event-types'
import eventTypes from 'dom-event-types'

interface TriggerOptions {
code?: String
Expand Down
20 changes: 11 additions & 9 deletions src/mount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ export function mount(
ref: MOUNT_COMPONENT_REF
})

const global = mergeGlobalProperties(config.global, options?.global)
component.components = { ...component.components, ...global.components }

// create the wrapper component
const Parent = defineComponent({
name: MOUNT_PARENT_NAME,
Expand All @@ -160,7 +163,6 @@ export function mount(

// create the app
const app = createApp(Parent)
const global = mergeGlobalProperties(config.global, options?.global)

// global mocks mixin
if (global?.mocks) {
Expand All @@ -176,34 +178,34 @@ export function mount(
}

// AppConfig
if (global?.config) {
if (global.config) {
for (const [k, v] of Object.entries(global.config)) {
app.config[k] = v
}
}

// use and plugins from mounting options
if (global?.plugins) {
if (global.plugins) {
for (const use of global.plugins) app.use(use)
}

// use any mixins from mounting options
if (global?.mixins) {
if (global.mixins) {
for (const mixin of global.mixins) app.mixin(mixin)
}

if (global?.components) {
if (global.components) {
for (const key of Object.keys(global.components))
app.component(key, global.components[key])
}

if (global?.directives) {
if (global.directives) {
for (const key of Object.keys(global.directives))
app.directive(key, global.directives[key])
}

// provide any values passed via provides mounting option
if (global?.provide) {
if (global.provide) {
for (const key of Reflect.ownKeys(global.provide)) {
// @ts-ignore: https://github.com/microsoft/TypeScript/issues/1863
app.provide(key, global.provide[key])
Expand All @@ -214,8 +216,8 @@ export function mount(
app.mixin(attachEmitListener())

// stubs
if (options?.global?.stubs || options?.shallow) {
stubComponents(options?.global?.stubs, options?.shallow)
if (global.stubs || options?.shallow) {
stubComponents(global.stubs, options?.shallow)
} else {
transformVNodeArgs()
}
Expand Down
49 changes: 29 additions & 20 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
import isString from 'lodash/isString'
import mergeWith from 'lodash/mergeWith'

import { GlobalMountOptions } from './types'

const isString = (val: unknown): val is string => typeof val === 'string'

function mergeStubs(target, source) {
if (source.stubs) {
if (Array.isArray(source.stubs)) {
source.stubs.forEach((x) => (target[x] = true))
} else {
for (const [k, v] of Object.entries(source.stubs)) {
target[k] = v
}
}
}
}

function mergeGlobalProperties(
configGlobal: GlobalMountOptions = {},
mountGlobal: GlobalMountOptions = {}
): GlobalMountOptions {
return mergeWith(
{},
configGlobal,
mountGlobal,
(objValue, srcValue, key: keyof GlobalMountOptions) => {
switch (key) {
case 'mocks':
case 'provide':
case 'components':
case 'directives':
return { ...objValue, ...srcValue }
case 'plugins':
case 'mixins':
return [...(objValue || []), ...(srcValue || [])].filter(Boolean)
}
}
)
const stubs: Record<string, any> = {}

mergeStubs(stubs, configGlobal)
mergeStubs(stubs, mountGlobal)

return {
mixins: [...(configGlobal.mixins || []), ...(mountGlobal.mixins || [])],
plugins: [...(configGlobal.plugins || []), ...(mountGlobal.plugins || [])],
stubs,
components: { ...configGlobal.components, ...mountGlobal.components },
provide: { ...configGlobal.provide, ...mountGlobal.provide },
mocks: { ...configGlobal.mocks, ...mountGlobal.mocks },
config: { ...configGlobal.config, ...mountGlobal.config },
directives: { ...configGlobal.directives, ...mountGlobal.directives }
}
}

export { isString, mergeGlobalProperties }
148 changes: 142 additions & 6 deletions tests/config.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { h, inject } from 'vue'
import { config, mount } from '../src'
import Hello from './components/Hello.vue'

Expand All @@ -11,20 +12,33 @@ describe('config', () => {
mocks: undefined,
provide: undefined
}

jest.clearAllMocks()
})

describe('components', () => {
const Component = {
template: '<div>{{ msg }} <hello/></div>',
components: { Hello },
template: '<div>{{ msg }} <Hello /></div>',
props: ['msg']
}

it('allows setting components globally', () => {
config.global.components = { Hello }
const wrapper1 = mount(Component, { props: { msg: 'Wrapper1' } })
const wrapper2 = mount(Component, { props: { msg: 'Wrapper2' } })
expect(wrapper1.text()).toEqual('Wrapper1 Hello world')
expect(wrapper2.text()).toEqual('Wrapper2 Hello world')
const HelloLocal = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a test if the locally registered component is overwritten properly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have this in the other test (I think?)

I will check.

name: 'Hello',
render() {
return h('div', 'Hello Local')
}
}
config.global.components = { Hello: HelloLocal }
const wrapper1 = mount(Component, {
props: { msg: 'Wrapper1' }
})
const wrapper2 = mount(Component, {
props: { msg: 'Wrapper2' }
})
expect(wrapper1.text()).toEqual('Wrapper1 Hello Local')
expect(wrapper2.text()).toEqual('Wrapper2 Hello Local')
})

it('allows overwriting globally set component config on a per mount instance', () => {
Expand Down Expand Up @@ -93,4 +107,126 @@ describe('config', () => {
).toEqual('baz')
})
})

describe('provide', () => {
const Comp = {
setup() {
const theme = inject('theme')
return () => h('div', theme)
}
}

it('sets a provide everywhere', () => {
config.global.provide = {
theme: 'dark'
}
const wrapper = mount(Comp)
expect(wrapper.html()).toContain('dark')
})

it('overrides with a local provide', () => {
config.global.provide = {
theme: 'dark'
}
const wrapper = mount(Comp, {
global: {
provide: {
theme: 'light'
}
}
})
expect(wrapper.html()).toContain('light')
})
})

describe('mixins', () => {
const createdHook = jest.fn()
const mixin = {
created() {
createdHook()
}
}
const Component = {
render() {
return h('div')
}
}

it('sets a mixin everywhere', () => {
config.global.mixins = [mixin]
mount(Component)

// once on root, once in the mounted component
expect(createdHook).toHaveBeenCalledTimes(2)
})

it('concats with locally defined mixins', () => {
config.global.mixins = [mixin]
const localHook = jest.fn()
const localMixin = {
created() {
localHook(this.$options.name)
}
}

mount(Component, {
global: {
mixins: [localMixin]
}
})

// once on root, once in the mounted component
expect(localHook).toHaveBeenCalledTimes(2)
expect(createdHook).toHaveBeenCalledTimes(2)
})
})

describe('stubs', () => {
const Foo = {
name: 'Foo',
render() {
return h('div', 'real foo')
}
}

const Component = {
render() {
return h('div', h(Foo))
}
}

beforeEach(() => {
config.global.stubs = {
Foo: {
name: 'Foo',
render() {
return h('div', 'config foo stub')
}
}
}
})

it('sets a stub globally', () => {
const wrapper = mount(Component)

// once on root, once in the mounted component
expect(wrapper.html()).toContain('config foo stub')
})

it('overrides config stub with locally defined stub', () => {
const wrapper = mount(Component, {
global: {
stubs: {
Foo: {
render() {
return h('div', 'local foo stub')
}
}
}
}
})

expect(wrapper.html()).toContain('local foo stub')
})
})
})