Skip to content

Commit 9380256

Browse files
committed
feat: implement tree-shaking-api transformation
1 parent ad1ce11 commit 9380256

File tree

6 files changed

+177
-0
lines changed

6 files changed

+177
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { defineInlineTest } from 'jscodeshift/src/testUtils'
2+
3+
const nextTick = require('../next-tick')
4+
const observable = require('../observable')
5+
const version = require('../version')
6+
const treeShaking = require('../tree-shaking')
7+
8+
// Vue.nextTick() => nextTick()
9+
defineInlineTest(
10+
nextTick,
11+
{},
12+
`import Vue from 'vue'
13+
Vue.nextTick(() => {
14+
console.log('foo')
15+
})
16+
`,
17+
`import Vue, { nextTick } from 'vue';
18+
nextTick(() => {
19+
console.log('foo')
20+
})
21+
`,
22+
'tree-shaking (Vue.nextTick() to nextTick())'
23+
)
24+
25+
// Vue.observable() => reactive()
26+
defineInlineTest(
27+
observable,
28+
{},
29+
`import Vue from 'vue'
30+
const state = Vue.observable({ count: 0 })`,
31+
`import Vue, { reactive } from 'vue';
32+
const state = reactive({ count: 0 })`,
33+
'tree-shaking (Vue.observable to reactive)'
34+
)
35+
36+
// Vue.version() => version()
37+
defineInlineTest(
38+
version,
39+
{},
40+
`import Vue from 'vue'
41+
var version = Number(Vue.version.split('.')[0])`,
42+
`import Vue, { version } from 'vue';
43+
var version = Number(version.split('.')[0])`,
44+
'tree-shaking (Vue.version to version)'
45+
)
46+
47+
defineInlineTest(
48+
treeShaking,
49+
{},
50+
`import Vue from 'vue'
51+
Vue.nextTick(function() {})
52+
Vue.observable({ count: 0 })
53+
Vue.version`,
54+
`import { nextTick, reactive, version } from 'vue';
55+
nextTick(function() {})
56+
reactive({ count: 0 })
57+
version
58+
`,
59+
'tree-shaking'
60+
)

transformations/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const transformationMap: {
2020
'rename-lifecycle': require('./rename-lifecycle'),
2121
'add-emit-declaration': require('./add-emit-declaration'),
2222
'global-filter': require('./global-filter'),
23+
'tree-shaking': require('./tree-shaking'),
2324

2425
// atomic ones
2526
'remove-contextual-h-from-render': require('./remove-contextual-h-from-render'),

transformations/next-tick.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import wrap from '../src/wrapAstTransformation'
2+
import type { ASTTransformation } from '../src/wrapAstTransformation'
3+
4+
export const transformAST: ASTTransformation = ({ root, j }) => {
5+
// find the Vue.nextTick(...)
6+
const nextTickCalls = root.find(j.CallExpression, n => {
7+
return (
8+
n.callee.type === 'MemberExpression' &&
9+
n.callee.property.name === 'nextTick' &&
10+
n.callee.object.name === 'Vue'
11+
)
12+
})
13+
14+
if (nextTickCalls.length) {
15+
// add import nextTick
16+
const addImport = require('./add-import')
17+
addImport.transformAST({ root, j }, {
18+
specifier: {
19+
type: 'named',
20+
imported: 'nextTick'
21+
},
22+
source: 'vue'
23+
})
24+
25+
nextTickCalls.replaceWith(({ node }) => {
26+
const el = node.arguments[0]
27+
return j.callExpression(j.identifier('nextTick'), [el])
28+
})
29+
}
30+
}
31+
32+
export default wrap(transformAST)
33+
export const parser = 'babylon'

transformations/observable.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import wrap from '../src/wrapAstTransformation'
2+
import type { ASTTransformation } from '../src/wrapAstTransformation'
3+
4+
export const transformAST: ASTTransformation = ({ root, j }) => {
5+
// find the Vue.observable(state)
6+
const observableCalls = root.find(j.CallExpression, n => {
7+
return (
8+
n.callee.type === 'MemberExpression' &&
9+
n.callee.property.name === 'observable' &&
10+
n.callee.object.name === 'Vue'
11+
)
12+
})
13+
14+
if (observableCalls.length) {
15+
// add import reactive
16+
const addImport = require('./add-import')
17+
addImport.transformAST({ root, j }, {
18+
specifier: {
19+
type: 'named',
20+
imported: 'reactive'
21+
},
22+
source: 'vue'
23+
})
24+
25+
observableCalls.replaceWith(({ node }) => {
26+
const el = node.arguments[0]
27+
return j.callExpression(j.identifier('reactive'), [el])
28+
})
29+
}
30+
}
31+
32+
export default wrap(transformAST)
33+
export const parser = 'babylon'

transformations/tree-shaking.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import wrap from '../src/wrapAstTransformation'
2+
import type { ASTTransformation } from '../src/wrapAstTransformation'
3+
import { transformAST as nextTick } from './next-tick'
4+
import { transformAST as observable } from './observable'
5+
import { transformAST as version } from './version'
6+
import { transformAST as removeImport } from './remove-extraneous-import'
7+
8+
export const transformAST: ASTTransformation = (context) => {
9+
nextTick(context)
10+
observable(context)
11+
version(context)
12+
13+
// remove import 'Vue' from 'vue' if not used
14+
removeImport(context, { localBinding: 'Vue' })
15+
}
16+
17+
export default wrap(transformAST)
18+
export const parser = 'babylon'

transformations/version.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import wrap from '../src/wrapAstTransformation'
2+
import type { ASTTransformation } from '../src/wrapAstTransformation'
3+
4+
export const transformAST: ASTTransformation = ({ root, j }) => {
5+
// find Vue.version
6+
const versionCalls = root.find(j.MemberExpression, n => {
7+
return (
8+
n.property.name === 'version' &&
9+
n.object.name === 'Vue'
10+
)
11+
})
12+
13+
if (versionCalls.length) {
14+
const addImport = require('./add-import')
15+
addImport.transformAST({ root, j }, {
16+
specifier: {
17+
type: 'named',
18+
imported: 'version'
19+
},
20+
source: 'vue'
21+
})
22+
23+
versionCalls.replaceWith(({ node }) => {
24+
// @ts-ignore
25+
const property = node.property.name
26+
return j.identifier(property)
27+
})
28+
}
29+
}
30+
31+
export default wrap(transformAST)
32+
export const parser = 'babylon'

0 commit comments

Comments
 (0)