From d8df1544c195378721027f6b37b513d92a6e2cbc Mon Sep 17 00:00:00 2001 From: sparklinm Date: Fri, 28 May 2021 17:19:46 +0800 Subject: [PATCH 01/20] =?UTF-8?q?feat:=20=E7=AE=80=E5=8D=95=E5=8E=BB?= =?UTF-8?q?=E9=99=A4=E6=96=87=E4=BB=B6=E5=86=85=E9=83=A8=E6=AD=BB=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/example/index.js | 61 +++++++ packages/wxa-cli/example/index.shaking.js | 39 +++++ packages/wxa-cli/example/user.js | 7 + packages/wxa-cli/src/tree-shake/index.js | 198 ++++++++++++++++++++++ packages/wxa-cli/src/tree-shake/scope.js | 0 5 files changed, 305 insertions(+) create mode 100644 packages/wxa-cli/example/index.js create mode 100644 packages/wxa-cli/example/index.shaking.js create mode 100644 packages/wxa-cli/example/user.js create mode 100644 packages/wxa-cli/src/tree-shake/index.js create mode 100644 packages/wxa-cli/src/tree-shake/scope.js diff --git a/packages/wxa-cli/example/index.js b/packages/wxa-cli/example/index.js new file mode 100644 index 00000000..8af10435 --- /dev/null +++ b/packages/wxa-cli/example/index.js @@ -0,0 +1,61 @@ +/* eslint-disable one-var */ +import getMyUser, {getName as getMyName} from './user'; +import * as user from './user'; + +let a = {x: 1}, + n = 1; +let t = a; +function m(x = 1, y) { + a = 5; + ++a; + t = 9; + let qqq = 10; +} + +m(); + +let ttt = function({x: xxx, y}) {}; + +let sss = (a, b) => {}; + +[1, 2, 3].forEach(function(item) {}); + +{ +} +if (a) { +} + +for (i = 0; i < 100; i++) {} + +class myclass {} + +export function mm() {} + +export {m as qqqqq, a}; + +function name(params) { + let t = {q: 1}; + let q = 2; + q++; + t.q; +} + +let obj = { + x: 1, + t() {}, +}; + +(function(x, y) {})(); + +export default { + x: 1, + t() {}, + m, + age, +}; +export * from './user'; +// export {x, y} from './a'; + +/** +export default function(){} +*/ diff --git a/packages/wxa-cli/example/index.shaking.js b/packages/wxa-cli/example/index.shaking.js new file mode 100644 index 00000000..4c16076c --- /dev/null +++ b/packages/wxa-cli/example/index.shaking.js @@ -0,0 +1,39 @@ +/* eslint-disable one-var */ +import './user'; +import './user'; +let a = { + x: 1, +}; +let t = a; + +function m(x = 1, y) { + a = 5; + ++a; + t = 9; +} + +m(); +[1, 2, 3].forEach(function(item) {}); +{} + +if (a) {} + +for (i = 0; i < 100; i++) {} + +export {m as qqqqq, a}; + +(function(x, y) {})(); + +export default { + x: 1, + + t() {}, + + m, + age, +}; +export * from './user'; // export {x, y} from './a'; + +/** +export default function(){} +*/ diff --git a/packages/wxa-cli/example/user.js b/packages/wxa-cli/example/user.js new file mode 100644 index 00000000..21b56668 --- /dev/null +++ b/packages/wxa-cli/example/user.js @@ -0,0 +1,7 @@ +export function getName() { + +} + +export default function getUser(params) { + +} diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js new file mode 100644 index 00000000..a291a737 --- /dev/null +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -0,0 +1,198 @@ +let fs = require('fs'); +let path = require('path'); +let mkdirp = require('mkdirp'); +const {parse} = require('@babel/parser'); +const traverse = require('@babel/traverse').default; +const generate = require('@babel/generator').default; +const t = require('@babel/types'); + +function readFile(p) { + let rst = ''; + p = typeof p === 'object' ? path.join(p.dir, p.base) : p; + try { + rst = fs.readFileSync(p, 'utf-8'); + } catch (e) { + rst = null; + } + + return rst; +} + +function writeFile(p, data) { + let opath = typeof p === 'string' ? path.parse(p) : p; + mkdirp.sync(opath.dir); + fs.writeFileSync(p, data); +} + +let entrySrc = path.resolve(__dirname, '../../example/index.js'); +let code = readFile(entrySrc); + +let ast = parse(code, {sourceType: 'unambiguous'}); + +class Scope { + constructor(options) { + options = options || {}; + + this.parent = options.parent; + this.depth = this.parent ? this.parent.depth + 1 : 0; + this.names = options.params || []; + this.nodes = {}; + this.isBlockScope = !!options.block; + } + // 添加变量名 + // isBlockDeclaration 是否是块级声明:let const class import + add(node, name, isBlockDeclaration) { + if (!isBlockDeclaration && this.isBlockScope) { + // it's a `var` or function declaration, and this + // is a block scope, so we need to go up + this.parent.add(node, name, isBlockDeclaration); + } else { + this.names.push(name); + this.nodes[name] = node; + } + } + + contains(name) { + return !!this.findDefiningScope(name); + } + + findDefiningScope(name) { + if (this.names.includes(name)) { + return this; + } + + if (this.parent) { + return this.parent.findDefiningScope(name); + } + + return null; + } +} + +let scope = new Scope(); + +function addToScope(node, attr, isBlockDeclaration = false) { + let identifierNode = node[attr]; + + if (t.isIdentifier(identifierNode)) { + identifierNode._skip = true; + } + + node._used = 0; + scope.add(node, identifierNode.name, isBlockDeclaration); +} + +console.time('ast'); +traverse(ast, { + enter(path) { + let {node} = path; + let childScope; + switch (node.type) { + // 函数声明 function a(){} + case 'FunctionDeclaration': + childScope = new Scope({ + parent: scope, + block: false, + }); + addToScope(node, 'id', false); + // 箭头函数 ()=>{} + case 'ArrowFunctionExpression': + // 函数表达式 function(){} + case 'FunctionExpression': + childScope = new Scope({ + parent: scope, + block: false, + }); + break; + // 块级作用域{} + case 'BlockStatement': + childScope = new Scope({ + parent: scope, + block: true, + }); + break; + // 变量声明 + case 'VariableDeclaration': + node.declarations.forEach((variableDeclarator) => { + if (node.kind === 'let' || node.kind === 'const') { + addToScope(variableDeclarator, 'id', true); + } else { + addToScope(variableDeclarator, 'id', false); + } + }); + break; + // 类的声明 + case 'ClassDeclaration': + addToScope(node, 'id', true); + break; + // import 的声明 + case 'ImportDeclaration': + node.specifiers.forEach((specifier) => { + addToScope(specifier, 'local', true); + }); + break; + } + + if (childScope) { + node._scope = childScope; + scope = childScope; + } + }, + + // 退出节点 + exit(path) { + let {node} = path; + if (node._scope) { + scope = scope.parent; + } + }, +}); +console.timeEnd('ast'); + + +traverse(ast, { + enter(path) { + let {node} = path; + + if (node._scope) { + scope = node._scope; + } + + if (t.isIdentifier(node) && !node._skip) { + let defineScope = scope.findDefiningScope(node.name); + if (defineScope) { + defineScope.nodes[node.name]._used = 1; + } + } + }, +}); + +traverse(ast, { + enter(path) { + let {node} = path; + + if (node._used === 0) { + path.remove(); + } + }, +}); + +const output = generate( + ast, + { + /* options */ + }, + code +); + +writeFile( + path.resolve(__dirname, '../../example/index.shaking.js'), + output.code +); + + +// function name(params) { +// console.log(m); +// } + +// name(); diff --git a/packages/wxa-cli/src/tree-shake/scope.js b/packages/wxa-cli/src/tree-shake/scope.js new file mode 100644 index 00000000..e69de29b From 2b64132adf0ecb4471d4075732c294965916a70a Mon Sep 17 00:00:00 2001 From: sparklinm Date: Sun, 30 May 2021 22:32:41 +0800 Subject: [PATCH 02/20] =?UTF-8?q?feat:=20=E5=88=86=E6=9E=90=E4=BE=9D?= =?UTF-8?q?=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/example/index.js | 6 +- .../{index.shaking.js => shaking/index.js} | 15 +- packages/wxa-cli/example/shaking/user.js | 0 packages/wxa-cli/src/tree-shake/index.js | 300 +++++++++++------- 4 files changed, 202 insertions(+), 119 deletions(-) rename packages/wxa-cli/example/{index.shaking.js => shaking/index.js} (68%) create mode 100644 packages/wxa-cli/example/shaking/user.js diff --git a/packages/wxa-cli/example/index.js b/packages/wxa-cli/example/index.js index 8af10435..e17a713a 100644 --- a/packages/wxa-cli/example/index.js +++ b/packages/wxa-cli/example/index.js @@ -6,6 +6,7 @@ let a = {x: 1}, n = 1; let t = a; function m(x = 1, y) { + a.x; a = 5; ++a; t = 9; @@ -31,7 +32,6 @@ class myclass {} export function mm() {} -export {m as qqqqq, a}; function name(params) { let t = {q: 1}; @@ -54,6 +54,10 @@ export default { age, }; export * from './user'; +export function getName() { + +} +export {m as qqqqq, a}; // export {x, y} from './a'; /** diff --git a/packages/wxa-cli/example/index.shaking.js b/packages/wxa-cli/example/shaking/index.js similarity index 68% rename from packages/wxa-cli/example/index.shaking.js rename to packages/wxa-cli/example/shaking/index.js index 4c16076c..3d5a18f5 100644 --- a/packages/wxa-cli/example/index.shaking.js +++ b/packages/wxa-cli/example/shaking/index.js @@ -1,28 +1,29 @@ +/* eslint-disable no-var */ + /* eslint-disable one-var */ import './user'; import './user'; let a = { - x: 1, + x: 1 }; let t = a; function m(x = 1, y) { a = 5; ++a; - t = 9; } m(); -[1, 2, 3].forEach(function(item) {}); +[1, 2, 3].forEach(function (item) {}); {} if (a) {} for (i = 0; i < 100; i++) {} -export {m as qqqqq, a}; +export { m as qqqqq, a }; -(function(x, y) {})(); +(function (x, y) {})(); export default { x: 1, @@ -30,10 +31,12 @@ export default { t() {}, m, - age, + age }; export * from './user'; // export {x, y} from './a'; /** export default function(){} */ + +var qqqqq = 1; \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/user.js b/packages/wxa-cli/example/shaking/user.js new file mode 100644 index 00000000..e69de29b diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index a291a737..a5b7da48 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -24,11 +24,6 @@ function writeFile(p, data) { fs.writeFileSync(p, data); } -let entrySrc = path.resolve(__dirname, '../../example/index.js'); -let code = readFile(entrySrc); - -let ast = parse(code, {sourceType: 'unambiguous'}); - class Scope { constructor(options) { options = options || {}; @@ -48,7 +43,12 @@ class Scope { this.parent.add(node, name, isBlockDeclaration); } else { this.names.push(name); - this.nodes[name] = node; + // 变量名可能重复,两个var声明同一变量 + if (this.nodes[name]) { + this.nodes[name].push(node); + } else { + this.nodes[name] = [node]; + } } } @@ -69,127 +69,203 @@ class Scope { } } -let scope = new Scope(); - -function addToScope(node, attr, isBlockDeclaration = false) { - let identifierNode = node[attr]; +class Graph { + constructor(entrySrc) { + this.entrySrc = entrySrc; + this.root = this.analysis(entrySrc); + } - if (t.isIdentifier(identifierNode)) { - identifierNode._skip = true; + getAbsolutePath(baseSrc, relativeSrc) { + return path.resolve(path.dirname(baseSrc), relativeSrc); } - node._used = 0; - scope.add(node, identifierNode.name, isBlockDeclaration); -} + analysis(src) { + let imports = {}; + let exports = {}; + let code = readFile(src); + let ast = parse(code, {sourceType: 'unambiguous'}); -console.time('ast'); -traverse(ast, { - enter(path) { - let {node} = path; - let childScope; - switch (node.type) { - // 函数声明 function a(){} - case 'FunctionDeclaration': - childScope = new Scope({ - parent: scope, - block: false, - }); - addToScope(node, 'id', false); - // 箭头函数 ()=>{} - case 'ArrowFunctionExpression': - // 函数表达式 function(){} - case 'FunctionExpression': - childScope = new Scope({ - parent: scope, - block: false, - }); - break; - // 块级作用域{} - case 'BlockStatement': - childScope = new Scope({ - parent: scope, - block: true, - }); - break; - // 变量声明 - case 'VariableDeclaration': - node.declarations.forEach((variableDeclarator) => { - if (node.kind === 'let' || node.kind === 'const') { - addToScope(variableDeclarator, 'id', true); - } else { - addToScope(variableDeclarator, 'id', false); - } - }); - break; - // 类的声明 - case 'ClassDeclaration': - addToScope(node, 'id', true); - break; - // import 的声明 - case 'ImportDeclaration': - node.specifiers.forEach((specifier) => { - addToScope(specifier, 'local', true); - }); - break; - } + let scope = new Scope(); + function addToScope(node, attr, isBlockDeclaration = false) { + let identifierNode = node[attr]; - if (childScope) { - node._scope = childScope; - scope = childScope; - } - }, + if (t.isIdentifier(identifierNode)) { + identifierNode._skip = true; + } - // 退出节点 - exit(path) { - let {node} = path; - if (node._scope) { - scope = scope.parent; + node._used = 0; + scope.add(node, identifierNode.name, isBlockDeclaration); } - }, -}); -console.timeEnd('ast'); + traverse(ast, { + enter: (path) => { + let {node} = path; + let childScope; + switch (node.type) { + // 函数声明 function a(){} + case 'FunctionDeclaration': + childScope = new Scope({ + parent: scope, + block: false, + }); + addToScope(node, 'id', false); + // 箭头函数 ()=>{} + case 'ArrowFunctionExpression': + // 函数表达式 function(){} + case 'FunctionExpression': + childScope = new Scope({ + parent: scope, + block: false, + }); + break; + // 块级作用域{} + case 'BlockStatement': + childScope = new Scope({ + parent: scope, + block: true, + }); + break; + // 变量声明 + case 'VariableDeclaration': + node.declarations.forEach((variableDeclarator) => { + if (node.kind === 'let' || node.kind === 'const') { + addToScope(variableDeclarator, 'id', true); + } else { + addToScope(variableDeclarator, 'id', false); + } + }); + break; + // 类的声明 + case 'ClassDeclaration': + addToScope(node, 'id', true); + break; + // import 的声明 + case 'ImportDeclaration': + node.specifiers.forEach((specifier) => { + addToScope(specifier, 'local', true); + }); -traverse(ast, { - enter(path) { - let {node} = path; + let depSrc = this.getAbsolutePath( + src, + node.source.value + '.js' + ); + imports[depSrc] = imports[depSrc] || []; + imports[depSrc] = imports[depSrc].concat([ + ...node.specifiers, + ]); + break; + // import 的声明 + case 'ExportNamedDeclaration': + exports[src] = exports[src] || []; + exports[src] = imports[src].concat([ + ...node.specifiers, + ]); + break; + } - if (node._scope) { - scope = node._scope; - } + if (childScope) { + node._scope = childScope; + scope = childScope; + } + }, + + // 退出节点 + exit(path) { + let {node} = path; + if (node._scope) { + scope = scope.parent; + } + }, + }); + + traverse(ast, { + enter(path) { + let {node} = path; + + if (node._scope) { + scope = node._scope; + } + + // obj.x 类型的属性访问,不算对x变量的使用 + if (t.isMemberExpression(node) && !node.computed) { + path.skip(); + } - if (t.isIdentifier(node) && !node._skip) { - let defineScope = scope.findDefiningScope(node.name); - if (defineScope) { - defineScope.nodes[node.name]._used = 1; + // TODO,怎么才算变量已经使用 + if (t.isIdentifier(node) && !node._skip) { + let defineScope = scope.findDefiningScope(node.name); + if (defineScope) { + defineScope.nodes[node.name].forEach((node) => { + node._used = 1; + }); + } + } + }, + // 退出节点 + exit(path) { + let {node} = path; + if (node._scope) { + scope = scope.parent; + } + }, + }); + + console.log(src); + console.log(imports); + console.log(exports); + + let dep = { + src, + code, + ast, + imports, + exports, + children: [], + scope, + }; + + Object.keys(dep.imports).forEach((childSrc, index) => { + dep.children[index] = this.analysis(childSrc); + }); + + return dep; + } +} + +let entrySrc = path.resolve(__dirname, '../../example/index.js'); +let graph = new Graph(entrySrc); +function run(dep) { + let {ast, scope, code, src} = dep; + + traverse(ast, { + enter(path) { + let {node} = path; + + if (node._used === 0) { + path.remove(); } - } - }, -}); + }, + }); -traverse(ast, { - enter(path) { - let {node} = path; + const output = generate( + ast, + { + /* options */ + }, + code + ); - if (node._used === 0) { - path.remove(); - } - }, -}); - -const output = generate( - ast, - { - /* options */ - }, - code -); - -writeFile( - path.resolve(__dirname, '../../example/index.shaking.js'), - output.code -); + writeFile( + path.resolve(path.dirname(src), './shaking', path.basename(src)), + output.code + ); + + dep.children.forEach((child) => { + run(child); + }); +} +run(graph.root); // function name(params) { // console.log(m); From 71eb4fb583d6698f5c0b5663d784c26754098a9e Mon Sep 17 00:00:00 2001 From: sparklinm Date: Fri, 4 Jun 2021 18:11:29 +0800 Subject: [PATCH 03/20] =?UTF-8?q?feat:=20=E7=AE=80=E5=8D=95=E8=BF=BD?= =?UTF-8?q?=E8=B8=AAimport/export?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/example/index.js | 40 ++- packages/wxa-cli/example/shaking/index.js | 28 +- packages/wxa-cli/example/shaking/user.js | 8 + packages/wxa-cli/example/user.js | 12 +- packages/wxa-cli/src/tree-shake/index.js | 315 ++++++++++++++++++++-- 5 files changed, 351 insertions(+), 52 deletions(-) diff --git a/packages/wxa-cli/example/index.js b/packages/wxa-cli/example/index.js index e17a713a..da89709d 100644 --- a/packages/wxa-cli/example/index.js +++ b/packages/wxa-cli/example/index.js @@ -2,6 +2,8 @@ import getMyUser, {getName as getMyName} from './user'; import * as user from './user'; + +console.console.log(getMyUser); let a = {x: 1}, n = 1; let t = a; @@ -28,10 +30,17 @@ if (a) { for (i = 0; i < 100; i++) {} -class myclass {} +class myclass { + [n]=1; + [n]=()=>{ + + } +} export function mm() {} +mm(); + function name(params) { let t = {q: 1}; @@ -47,19 +56,34 @@ let obj = { (function(x, y) {})(); -export default { - x: 1, - t() {}, - m, - age, -}; +// export default { +// x: 1, +// t() {}, +// m, +// age, +// }; export * from './user'; export function getName() { } -export {m as qqqqq, a}; +export {m as qqqqq, a as default}; + // export {x, y} from './a'; /** export default function(){} */ + +export {ss1s}; +// eslint-disable-next-line no-var +let ss1s=1; + +export { + mm as ttttttt, +}; + +export {getName as tttt} from './user'; + + +export * as tttttt from 'user'; + diff --git a/packages/wxa-cli/example/shaking/index.js b/packages/wxa-cli/example/shaking/index.js index 3d5a18f5..f869cb9e 100644 --- a/packages/wxa-cli/example/shaking/index.js +++ b/packages/wxa-cli/example/shaking/index.js @@ -1,5 +1,3 @@ -/* eslint-disable no-var */ - /* eslint-disable one-var */ import './user'; import './user'; @@ -9,8 +7,10 @@ let a = { let t = a; function m(x = 1, y) { + a.x; a = 5; ++a; + t = 9; } m(); @@ -21,22 +21,20 @@ if (a) {} for (i = 0; i < 100; i++) {} -export { m as qqqqq, a }; - -(function (x, y) {})(); +export function mm() {} -export default { - x: 1, +(function (x, y) {})(); // export default { +// x: 1, +// t() {}, +// m, +// age, +// }; - t() {}, - m, - age -}; -export * from './user'; // export {x, y} from './a'; +export * from './user'; +export function getName() {} +export { m as qqqqq, a as default }; // export {x, y} from './a'; /** export default function(){} -*/ - -var qqqqq = 1; \ No newline at end of file +*/ \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/user.js b/packages/wxa-cli/example/shaking/user.js index e69de29b..85fd8cb7 100644 --- a/packages/wxa-cli/example/shaking/user.js +++ b/packages/wxa-cli/example/shaking/user.js @@ -0,0 +1,8 @@ +export function getName() {} // export default function getUser(params) { +// } + +let a = 1; +export default a; // eslint-disable-next-line one-var + +export let mm1 = 1, + c = function mm2(params) {}; \ No newline at end of file diff --git a/packages/wxa-cli/example/user.js b/packages/wxa-cli/example/user.js index 21b56668..3b5a254a 100644 --- a/packages/wxa-cli/example/user.js +++ b/packages/wxa-cli/example/user.js @@ -2,6 +2,14 @@ export function getName() { } -export default function getUser(params) { +// export default function getUser(params) { -} +// } + +let a =1; +export default a; + +// eslint-disable-next-line one-var +export let mm1 =1, c=function mm2(params) { + +}; diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index a5b7da48..57116144 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -79,6 +79,22 @@ class Graph { return path.resolve(path.dirname(baseSrc), relativeSrc); } + getExpSrc(node, src) { + let expSrc = ''; + + if (node.source) { + expSrc = this.getAbsolutePath(src, node.source.value + '.js'); + } else { + expSrc = src; + } + + return expSrc; + } + + markShakingFlag(node) { + node._shake = 1; + } + analysis(src) { let imports = {}; let exports = {}; @@ -93,7 +109,7 @@ class Graph { identifierNode._skip = true; } - node._used = 0; + node._usedNodes = []; scope.add(node, identifierNode.name, isBlockDeclaration); } @@ -145,21 +161,81 @@ class Graph { addToScope(specifier, 'local', true); }); - let depSrc = this.getAbsolutePath( + let impSrc = this.getAbsolutePath( src, node.source.value + '.js' ); - imports[depSrc] = imports[depSrc] || []; - imports[depSrc] = imports[depSrc].concat([ - ...node.specifiers, - ]); + imports[impSrc] = imports[impSrc] || {}; + node.specifiers.forEach((specifier) => { + let name = + specifier.imported && specifier.imported.name; + if (!name) { + if ( + specifier.type === 'ImportDefaultSpecifier' + ) { + name = 'default'; + } else if ( + specifier.type === + 'ImportNamespaceSpecifier' + ) { + name = '*'; + } + } + imports[impSrc][name] = specifier; + }); break; - // import 的声明 + // export 的声明 case 'ExportNamedDeclaration': - exports[src] = exports[src] || []; - exports[src] = imports[src].concat([ - ...node.specifiers, - ]); + let expSrc = this.getExpSrc(node, src); + + exports[expSrc] = exports[expSrc] || {}; + + if (node.specifiers && node.specifiers.length) { + node.specifiers.forEach((specifier) => { + let name = specifier.exported.name; + exports[expSrc][name] = specifier; + this.markShakingFlag(specifier); + }); + } else { + let declaration = node.declaration; + + if (declaration.type === 'FunctionDeclaration') { + let name = declaration.id.name; + exports[expSrc][name] = declaration; + declaration._shake = 1; + this.markShakingFlag(declaration); + } else if ( + declaration.type === 'VariableDeclaration' + ) { + declaration.declarations.forEach( + (variableDeclarator) => { + let name = variableDeclarator.id.name; + exports[expSrc][name] = + variableDeclarator; + this.markShakingFlag( + variableDeclarator + ); + } + ); + } else if ( + declaration.type === 'ClassDeclaration' + ) { + let name = declaration.id.name; + exports[expSrc][name] = declaration; + this.markShakingFlag(declaration); + } + } + break; + case 'ExportDefaultDeclaration': + exports[src] = exports[src] || {}; + exports[src].default = node; + this.markShakingFlag(node); + break; + case 'ExportAllDeclaration': + let exportSrc = this.getExpSrc(node, src); + exports[exportSrc] = exports[exportSrc] || {}; + exports[exportSrc]['*'] = node; + this.markShakingFlag(node); break; } @@ -178,27 +254,71 @@ class Graph { }, }); + function findScope(node) { + let defineScope = scope.findDefiningScope(node.name); + if (defineScope) { + defineScope.nodes[node.name].forEach((node) => { + node._usedNodes.push(node); + }); + } + } + traverse(ast, { - enter(path) { + enter: (path) => { let {node} = path; if (node._scope) { scope = node._scope; } - // obj.x 类型的属性访问,不算对x变量的使用 - if (t.isMemberExpression(node) && !node.computed) { - path.skip(); - } + // else if (node.type === 'ExportNamedDeclaration') { + // node.specifiers.forEach((specifier) => { + // let nodes = scope.nodes[specifier.local.name]; + // if (nodes) { + // nodes.forEach((node) => { + // this.markShakingFlag(node); + // }); + + // specifier._referenceNodes = nodes; + // } + // }); + // } else if ( + // // export default {} + // node.type === 'ExportDefaultDeclaration' && + // node.declaration.type === 'ObjectExpression' + // ) { + // node.declaration.properties.forEach((p)=>{ + // if (p.computed) { + // let nodes = scope.nodes[p.key.name]; + // if (nodes) { + // node._referenceNodes = nodes; + // } + // } + // // let nodes + // // TODO,如何判断对象属性中对外部变量的引用 + // }); + // } - // TODO,怎么才算变量已经使用 - if (t.isIdentifier(node) && !node._skip) { - let defineScope = scope.findDefiningScope(node.name); - if (defineScope) { - defineScope.nodes[node.name].forEach((node) => { - node._used = 1; - }); - } + // obj.x 类型的属性访问,不算对x变量的使用 + if (node.type === 'MemberExpression') { + !node.computed && path.skip(); + } else if (node.type === 'ObjectProperty') { + // {x:1} 对象属性 + !node.computed && path.skipKey('key'); + } else if ( + [ + 'ClassMethod', + 'ClassPrivateMethod', + 'ClassProperty', + 'ClassDeclaration', + ].includes(node.type) + ) { + !node.computed && path.skipKey('key'); + } else if (t.isIdentifier(node)) { + // TODO,怎么才算变量已经使用 + // 这里的判断不准确,无法判断类似函数a引用函数b,但a并没有没使用到 + // 这里只会去除掉函数a,去除不了函数b + !node._skip && findScope(node); } }, // 退出节点 @@ -211,8 +331,41 @@ class Graph { }); console.log(src); - console.log(imports); - console.log(exports); + console.log('imports', imports); + console.log('exports', exports); + + // import * 和 export * 不包括default + // export * from '' 和 export 本文件冲突,export 本文件优先级更高 + // export * from '' 互相冲突,后export * from '' 优先 + // export {} from '', 从其他文件导出,导出的变量无法在本文件使用 + /** + * imports: { + * [路径]: { + * [name]: ImportSpecifier, + * default: ImportDefaultSpecifier, + * *: ImportNamespaceSpecifier + * } + * } + * + * exports: { + * [本文件路径]: { + * // export function(){} + * [name]: FunctionDeclaration|VariableDeclaration|ClassDeclaration + * // export default function(){} | export default{} | export {a as default} | export default a + * default: ExportDefaultDeclaration | ExportSpecifier, + * // export {a as aaa,b,c} + * [name]: ExportSpecifier + * }, + * [其他路径]: { + * // export {a as aaa,b,c} from '' | export * as all from '' + * [name]: ExportSpecifier + * // export {default} from '' | export {a as default} from '' | export * as default from '' + * default: ExportSpecifier, + * // export * from '' + * *: ExportAllDeclaration + * }, + * } + */ let dep = { src, @@ -224,6 +377,8 @@ class Graph { scope, }; + // TODO,只是imports节点不准确 + // export {} from './a' a 文件也是子节点 Object.keys(dep.imports).forEach((childSrc, index) => { dep.children[index] = this.analysis(childSrc); }); @@ -234,6 +389,111 @@ class Graph { let entrySrc = path.resolve(__dirname, '../../example/index.js'); let graph = new Graph(entrySrc); + +/** + * export node 有一个_shake标志,如果该export没有被import,或者被import后没有使用,_shake = 1 + * 输出时,判断export node 的_shake,当等于1时,遍历子节点,看是否有声明节点,如果声明节点未被引用才可以shake掉 + * + */ + +function shake(dep) { + let imports = dep.imports; + + let mark = (dep, usedNames, childSrc) => { + if (usedNames.length) { + let child = dep.children.find((child) => child.src === childSrc); + let exportsArray = Object.entries(child.exports); + let localIndex = exportsArray.findIndex( + ([src]) => src == child.src + ); + let localExports = null; + let externalExports = [...exportsArray]; + if (localIndex !== -1) { + localExports = externalExports.splice(localIndex, 1); + } + + let hasAll = usedNames.some((name) => name === '*'); + let usedExports = {}; + let addUsedExport = (src, node) => { + usedExports[src] = usedExports[src] || {}; + let local = node.local; + if (local) { + usedExports[src][local.name] = node; + } else { + usedExports[src]['*'] = node; + } + }; + if (hasAll) { + let hasDefalut = usedNames.some((name) => name === 'default'); + let markedDefalut = false; + if (localExports) { + localExports.forEach(([src, value]) => { + Object.entries(value).forEach(([name, node]) => { + if (name === 'default') { + if (hasDefalut) { + node._shake = 0; + markedDefalut = true; + } + } else { + node._shake = 0; + } + }); + }); + } + + externalExports.forEach(([src, value]) => { + Object.entries(value).forEach(([name, node]) => { + if ( + (name === 'default' && + hasDefalut && + !markedDefalut) || + name !== 'default' + ) { + node._shake = 0; + addUsedExport(src, node); + } + }); + }); + } else { + usedNames.forEach((name) => { + if (localExports) { + let node = localExports[1][name]; + if (node) { + node._shake = 0; + return; + } + } + + externalExports.forEach(([src, value]) => { + let node = value[name] || value['*']; + if (node) { + node._shake = 0; + addUsedExport(src, node); + } + }); + }); + } + + Object.entries(usedExports).forEach((src, value)=>{ + mark(child, Object.keys(value), src); + }); + } + }; + + Object.entries(imports).forEach(([src, value], index) => { + let usedNames = []; + + Object.entries(value).forEach(([name, node]) => { + if (node._usedNodes && node._usedNodes.length) { + usedNames.push(name); + } + }); + mark(dep, usedNames, src); + }); + + dep.children.forEach((child)=>shake(child)); +} + function run(dep) { let {ast, scope, code, src} = dep; @@ -241,7 +501,7 @@ function run(dep) { enter(path) { let {node} = path; - if (node._used === 0) { + if (node._usedNodes && node._usedNodes.length === 0) { path.remove(); } }, @@ -265,6 +525,7 @@ function run(dep) { }); } +// shake(graph.root); run(graph.root); // function name(params) { From 7b6e4161495464e81eb2da5753d2e2ff5af1cd24 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Sun, 6 Jun 2021 22:52:28 +0800 Subject: [PATCH 04/20] =?UTF-8?q?fix:=20=E4=B8=80=E4=BA=9B=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/src/tree-shake/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index 57116144..645cf330 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -387,8 +387,6 @@ class Graph { } } -let entrySrc = path.resolve(__dirname, '../../example/index.js'); -let graph = new Graph(entrySrc); /** * export node 有一个_shake标志,如果该export没有被import,或者被import后没有使用,_shake = 1 @@ -525,7 +523,9 @@ function run(dep) { }); } -// shake(graph.root); +let entrySrc = path.resolve(__dirname, '../../example/index.js'); +let graph = new Graph(entrySrc); +shake(graph.root); run(graph.root); // function name(params) { From 95ae6eccf303188f78446cea7c2a6ca0d18ef249 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Mon, 7 Jun 2021 20:04:01 +0800 Subject: [PATCH 05/20] =?UTF-8?q?feat:=20=E5=88=9D=E6=AD=A5=E5=AE=8C?= =?UTF-8?q?=E6=88=90tree-shake?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/example/index.js | 27 ++- packages/wxa-cli/example/shaking/index.js | 30 ++-- packages/wxa-cli/example/shaking/user.js | 4 +- packages/wxa-cli/src/tree-shake/index.js | 197 ++++++++++++++++------ 4 files changed, 173 insertions(+), 85 deletions(-) diff --git a/packages/wxa-cli/example/index.js b/packages/wxa-cli/example/index.js index da89709d..9b1b41be 100644 --- a/packages/wxa-cli/example/index.js +++ b/packages/wxa-cli/example/index.js @@ -3,18 +3,17 @@ import getMyUser, {getName as getMyName} from './user'; import * as user from './user'; -console.console.log(getMyUser); +console.log(user); let a = {x: 1}, n = 1; -let t = a; +let t = 10; function m(x = 1, y) { - a.x; a = 5; ++a; t = 9; + t+5; let qqq = 10; } - m(); let ttt = function({x: xxx, y}) {}; @@ -25,12 +24,11 @@ let sss = (a, b) => {}; { } -if (a) { -} + for (i = 0; i < 100; i++) {} -class myclass { +class Myclass { [n]=1; [n]=()=>{ @@ -56,9 +54,12 @@ let obj = { (function(x, y) {})(); + +getName(); // export default { // x: 1, -// t() {}, +// t() { +// }, // m, // age, // }; @@ -66,17 +67,14 @@ export * from './user'; export function getName() { } -export {m as qqqqq, a as default}; +// export {m as qqqqq, a as default}; // export {x, y} from './a'; -/** -export default function(){} -*/ +export default function() {} -export {ss1s}; +export {Myclass}; // eslint-disable-next-line no-var -let ss1s=1; export { mm as ttttttt, @@ -87,3 +85,4 @@ export {getName as tttt} from './user'; export * as tttttt from 'user'; + diff --git a/packages/wxa-cli/example/shaking/index.js b/packages/wxa-cli/example/shaking/index.js index f869cb9e..508d0dbc 100644 --- a/packages/wxa-cli/example/shaking/index.js +++ b/packages/wxa-cli/example/shaking/index.js @@ -1,40 +1,44 @@ /* eslint-disable one-var */ import './user'; -import './user'; +import * as user from './user'; +console.log(user); let a = { - x: 1 + x: 1, }; let t = a; function m(x = 1, y) { - a.x; + // eslint-disable-next-line no-tabs a = 5; ++a; t = 9; } m(); -[1, 2, 3].forEach(function (item) {}); +[1, 2, 3].forEach(function(item) {}); {} -if (a) {} for (i = 0; i < 100; i++) {} export function mm() {} +mm(); + +(function(x, y) {})(); -(function (x, y) {})(); // export default { +getName(); // export default { // x: 1, -// t() {}, +// t() { +// }, // m, // age, // }; +export function getName() {} // export {m as qqqqq, a as default}; +// export {x, y} from './a'; -export * from './user'; -export function getName() {} -export { m as qqqqq, a as default }; // export {x, y} from './a'; +export {}; // eslint-disable-next-line no-var -/** -export default function(){} -*/ \ No newline at end of file +export {}; +export {} from './user'; +export {} from 'user'; diff --git a/packages/wxa-cli/example/shaking/user.js b/packages/wxa-cli/example/shaking/user.js index 85fd8cb7..af191737 100644 --- a/packages/wxa-cli/example/shaking/user.js +++ b/packages/wxa-cli/example/shaking/user.js @@ -1,8 +1,6 @@ export function getName() {} // export default function getUser(params) { // } -let a = 1; -export default a; // eslint-disable-next-line one-var - +// eslint-disable-next-line one-var export let mm1 = 1, c = function mm2(params) {}; \ No newline at end of file diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index 645cf330..71559b4a 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -33,6 +33,10 @@ class Scope { this.names = options.params || []; this.nodes = {}; this.isBlockScope = !!options.block; + this.children = []; + if (this.parent) { + this.parent.children.push(this); + } } // 添加变量名 // isBlockDeclaration 是否是块级声明:let const class import @@ -99,17 +103,23 @@ class Graph { let imports = {}; let exports = {}; let code = readFile(src); - let ast = parse(code, {sourceType: 'unambiguous'}); + let ast = parse(code, { + sourceType: 'unambiguous', + plugins: ['classProperties'], + }); let scope = new Scope(); function addToScope(node, attr, isBlockDeclaration = false) { let identifierNode = node[attr]; - if (t.isIdentifier(identifierNode)) { - identifierNode._skip = true; + // 类似于export default function(){} + if (!identifierNode || !identifierNode.name) { + return; } - node._usedNodes = []; + identifierNode._skip = true; + + node._usedByNodes = []; scope.add(node, identifierNode.name, isBlockDeclaration); } @@ -257,8 +267,8 @@ class Graph { function findScope(node) { let defineScope = scope.findDefiningScope(node.name); if (defineScope) { - defineScope.nodes[node.name].forEach((node) => { - node._usedNodes.push(node); + defineScope.nodes[node.name].forEach((declarationNode) => { + declarationNode._usedByNodes.push(node); }); } } @@ -271,34 +281,6 @@ class Graph { scope = node._scope; } - // else if (node.type === 'ExportNamedDeclaration') { - // node.specifiers.forEach((specifier) => { - // let nodes = scope.nodes[specifier.local.name]; - // if (nodes) { - // nodes.forEach((node) => { - // this.markShakingFlag(node); - // }); - - // specifier._referenceNodes = nodes; - // } - // }); - // } else if ( - // // export default {} - // node.type === 'ExportDefaultDeclaration' && - // node.declaration.type === 'ObjectExpression' - // ) { - // node.declaration.properties.forEach((p)=>{ - // if (p.computed) { - // let nodes = scope.nodes[p.key.name]; - // if (nodes) { - // node._referenceNodes = nodes; - // } - // } - // // let nodes - // // TODO,如何判断对象属性中对外部变量的引用 - // }); - // } - // obj.x 类型的属性访问,不算对x变量的使用 if (node.type === 'MemberExpression') { !node.computed && path.skip(); @@ -314,7 +296,7 @@ class Graph { ].includes(node.type) ) { !node.computed && path.skipKey('key'); - } else if (t.isIdentifier(node)) { + } else if (node.type === 'Identifier') { // TODO,怎么才算变量已经使用 // 这里的判断不准确,无法判断类似函数a引用函数b,但a并没有没使用到 // 这里只会去除掉函数a,去除不了函数b @@ -330,14 +312,15 @@ class Graph { }, }); - console.log(src); - console.log('imports', imports); - console.log('exports', exports); + // console.log(src); + // console.log('imports', imports); + // console.log('exports', exports); // import * 和 export * 不包括default // export * from '' 和 export 本文件冲突,export 本文件优先级更高 // export * from '' 互相冲突,后export * from '' 优先 // export {} from '', 从其他文件导出,导出的变量无法在本文件使用 + // export default function(){},导出的函数没有name,不能再本文件使用 /** * imports: { * [路径]: { @@ -387,7 +370,6 @@ class Graph { } } - /** * export node 有一个_shake标志,如果该export没有被import,或者被import后没有使用,_shake = 1 * 输出时,判断export node 的_shake,当等于1时,遍历子节点,看是否有声明节点,如果声明节点未被引用才可以shake掉 @@ -407,7 +389,7 @@ function shake(dep) { let localExports = null; let externalExports = [...exportsArray]; if (localIndex !== -1) { - localExports = externalExports.splice(localIndex, 1); + localExports = externalExports.splice(localIndex, 1)[0]; } let hasAll = usedNames.some((name) => name === '*'); @@ -425,17 +407,15 @@ function shake(dep) { let hasDefalut = usedNames.some((name) => name === 'default'); let markedDefalut = false; if (localExports) { - localExports.forEach(([src, value]) => { - Object.entries(value).forEach(([name, node]) => { - if (name === 'default') { - if (hasDefalut) { - node._shake = 0; - markedDefalut = true; - } - } else { + Object.entries(localExports[1]).forEach(([name, node]) => { + if (name === 'default') { + if (hasDefalut) { node._shake = 0; + markedDefalut = true; } - }); + } else { + node._shake = 0; + } }); } @@ -472,7 +452,7 @@ function shake(dep) { }); } - Object.entries(usedExports).forEach((src, value)=>{ + Object.entries(usedExports).forEach((src, value) => { mark(child, Object.keys(value), src); }); } @@ -482,24 +462,96 @@ function shake(dep) { let usedNames = []; Object.entries(value).forEach(([name, node]) => { - if (node._usedNodes && node._usedNodes.length) { + if (node._usedByNodes && node._usedByNodes.length) { usedNames.push(name); } }); mark(dep, usedNames, src); }); - dep.children.forEach((child)=>shake(child)); + dep.children.forEach((child) => shake(child)); +} + +function remove(dep) { + let {ast, scope, code, src, exports} = dep; + let loop = true; + let doRemove = (scope) => { + let {nodes: allNodes} = scope; + Object.values(allNodes).forEach((nodes) => { + nodes.forEach((node) => { + if (node._removed === 1) { + return; + } + + if (t.isClassDeclaration(node)) { + console.log('--------------'); + console.log(node._usedByNodes[0]); + } + + if ( + (node._usedByNodes.length === 0 && + (node._shake === 1 || node._shake === undefined)) || + (node._usedByNodes.length !== 0 && + node._usedByNodes.every( + (node) => node._removed || node._shake === 1 + )) + ) { + node._removed = 1; + loop = true; + + traverse(node, { + noScope: true, + enter(path) { + let {node} = path; + node._removed = 1; + }, + }); + } + }); + }); + + scope.children.forEach((childScope) => { + doRemove(childScope); + }); + }; + + while (loop) { + Object.entries(exports).forEach(([src, value]) => { + Object.entries(value).forEach(([name, node]) => { + if ( + node._shake === 1 && + (!node._usedByNodes || + (node._usedByNodes && node._usedByNodes.length === 0)) + ) { + traverse(node, { + noScope: true, + enter(path) { + let {node} = path; + node._shake = 1; + }, + }); + } else { + node._shake = 0; + } + }); + }); + loop = false; + doRemove(scope); + } + + dep.children.forEach((child) => remove(child)); } function run(dep) { - let {ast, scope, code, src} = dep; + let {ast, code, src} = dep; traverse(ast, { enter(path) { let {node} = path; - - if (node._usedNodes && node._usedNodes.length === 0) { + if ( + node._removed === 1 || + (!node._usedByNodes && node._shake === 1) + ) { path.remove(); } }, @@ -523,13 +575,48 @@ function run(dep) { }); } +console.time('end'); let entrySrc = path.resolve(__dirname, '../../example/index.js'); let graph = new Graph(entrySrc); shake(graph.root); +remove(graph.root); run(graph.root); +console.timeEnd('end'); // function name(params) { // console.log(m); // } // name(); + +// let code = `function scopeOnce() { +// var ref = "This is a binding"; +// var xx = 'binding2' + +// if(xx){ +// let oo="binding3" +// } + +// ref + '1'; // This is a reference to a binding + +// function scopeTwo() { +// ref+'2'; // This is a reference to a binding from a lower scope +// } +// }`; +// let ast = parse(code, {sourceType: 'unambiguous'}); +// traverse(ast, { +// enter(path) { +// let {node} =path; +// if (node.type === 'VariableDeclarator') { +// console.log(path.scope); +// } +// }, +// }); + +// console.log(generate( +// ast, +// { +// /* options */ +// }, +// code +// ).code); From cce98cf427e91600082c42175ab4f39a51a3f710 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Wed, 9 Jun 2021 11:20:23 +0800 Subject: [PATCH 06/20] =?UTF-8?q?feat:=20=E4=BB=A3=E7=A0=81=E6=95=B4?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/example/shaking/index.js | 5 +- packages/wxa-cli/src/my.html | 18 + packages/wxa-cli/src/tree-shake/graph.js | 292 +++++++++++++++ packages/wxa-cli/src/tree-shake/index.js | 435 +++------------------- packages/wxa-cli/src/tree-shake/scope.js | 53 +++ packages/wxa-cli/src/tree-shake/util.js | 26 ++ 6 files changed, 453 insertions(+), 376 deletions(-) create mode 100644 packages/wxa-cli/src/my.html create mode 100644 packages/wxa-cli/src/tree-shake/graph.js create mode 100644 packages/wxa-cli/src/tree-shake/util.js diff --git a/packages/wxa-cli/example/shaking/index.js b/packages/wxa-cli/example/shaking/index.js index 508d0dbc..b64b1d09 100644 --- a/packages/wxa-cli/example/shaking/index.js +++ b/packages/wxa-cli/example/shaking/index.js @@ -5,20 +5,19 @@ console.log(user); let a = { x: 1, }; -let t = a; +let t = 10; function m(x = 1, y) { - // eslint-disable-next-line no-tabs a = 5; ++a; t = 9; + t + 5; } m(); [1, 2, 3].forEach(function(item) {}); {} - for (i = 0; i < 100; i++) {} export function mm() {} diff --git a/packages/wxa-cli/src/my.html b/packages/wxa-cli/src/my.html new file mode 100644 index 00000000..ae101b94 --- /dev/null +++ b/packages/wxa-cli/src/my.html @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/packages/wxa-cli/src/tree-shake/graph.js b/packages/wxa-cli/src/tree-shake/graph.js new file mode 100644 index 00000000..7ebbe529 --- /dev/null +++ b/packages/wxa-cli/src/tree-shake/graph.js @@ -0,0 +1,292 @@ +const path = require('path'); +const {parse} = require('@babel/parser'); +const traverse = require('@babel/traverse').default; +const {Scope} = require('./scope'); +const {readFile} = require('./util'); + +class Graph { + constructor(entrySrc) { + this.entrySrc = entrySrc; + this.root = this.analysis(entrySrc); + } + + getAbsolutePath(baseSrc, relativeSrc) { + return path.resolve(path.dirname(baseSrc), relativeSrc); + } + + getExpSrc(node, src) { + let expSrc = ''; + + if (node.source) { + expSrc = this.getAbsolutePath(src, node.source.value + '.js'); + } else { + expSrc = src; + } + + return expSrc; + } + + collectDeclaration(path, scope) { + function addToScope(node, attr, isBlockDeclaration = false) { + let identifierNode = node[attr]; + + // 类似于export default function(){} + if (!identifierNode || !identifierNode.name) { + return; + } + + identifierNode._skip = true; + + node._usedByNodes = []; + scope.add(node, identifierNode.name, isBlockDeclaration); + } + + let {node} = path; + let childScope; + + switch (node.type) { + // 函数声明 function a(){} + case 'FunctionDeclaration': + childScope = new Scope({ + parent: scope, + block: false, + }); + addToScope(node, 'id', false); + // 箭头函数 ()=>{} + case 'ArrowFunctionExpression': + // 函数表达式 function(){} + case 'FunctionExpression': + childScope = new Scope({ + parent: scope, + block: false, + }); + break; + // 块级作用域{} + case 'BlockStatement': + childScope = new Scope({ + parent: scope, + block: true, + }); + break; + // 变量声明 + case 'VariableDeclaration': + node.declarations.forEach((variableDeclarator) => { + if (node.kind === 'let' || node.kind === 'const') { + addToScope(variableDeclarator, 'id', true); + } else { + addToScope(variableDeclarator, 'id', false); + } + }); + break; + // 类的声明 + case 'ClassDeclaration': + addToScope(node, 'id', true); + break; + // import 的声明 + case 'ImportDeclaration': + node.specifiers.forEach((specifier) => { + addToScope(specifier, 'local', true); + }); + break; + } + + return childScope; + } + + collectImport(path) { + let {node} = path; + let importInfo = null; + + switch (node.type) { + // import 的声明 + case 'ImportDeclaration': + importInfo = {}; + node.specifiers.forEach((specifier) => { + let name = specifier.imported && specifier.imported.name; + if (!name) { + if (specifier.type === 'ImportDefaultSpecifier') { + name = 'default'; + } else if ( + specifier.type === 'ImportNamespaceSpecifier' + ) { + name = '*'; + } + } + importInfo[name] = specifier; + }); + break; + } + + return importInfo; + } + + collectExport(path) { + let {node} = path; + let exportInfo = null; + + let markShakingFlag = (node) => { + node._shake = 1; + }; + + switch (node.type) { + // export 的声明 + case 'ExportNamedDeclaration': + exportInfo = {}; + if (node.specifiers && node.specifiers.length) { + node.specifiers.forEach((specifier) => { + let name = specifier.exported.name; + exportInfo[name] = specifier; + markShakingFlag(specifier); + }); + } else { + let declaration = node.declaration; + + if (declaration.type === 'FunctionDeclaration') { + let name = declaration.id.name; + exportInfo[name] = declaration; + declaration._shake = 1; + markShakingFlag(declaration); + } else if (declaration.type === 'VariableDeclaration') { + declaration.declarations.forEach( + (variableDeclarator) => { + let name = variableDeclarator.id.name; + exportInfo[name] = variableDeclarator; + markShakingFlag(variableDeclarator); + } + ); + } else if (declaration.type === 'ClassDeclaration') { + let name = declaration.id.name; + exportInfo[name] = declaration; + markShakingFlag(declaration); + } + } + break; + case 'ExportDefaultDeclaration': + exportInfo = {}; + exportInfo.default = node; + markShakingFlag(node); + break; + case 'ExportAllDeclaration': + exportInfo = {}; + exportInfo['*'] = node; + markShakingFlag(node); + break; + } + + return exportInfo; + } + + analysis(src) { + let imports = {}; + let exports = {}; + let code = readFile(src); + let ast = parse(code, { + sourceType: 'unambiguous', + plugins: ['classProperties'], + }); + + let scope = new Scope(); + + traverse(ast, { + enter: (path) => { + let {node} = path; + + let childScope = this.collectDeclaration(path, scope); + if (childScope) { + node._scope = childScope; + scope = childScope; + } + + let importInfo = this.collectImport(path); + if (importInfo) { + let impSrc = this.getAbsolutePath( + src, + node.source.value + '.js' + ); + imports[impSrc] = imports[impSrc] || {}; + imports[impSrc] = {...imports[impSrc], ...importInfo}; + } + + let exportInfo = this.collectExport(path); + if (exportInfo) { + let expSrc = this.getExpSrc(node, src); + exports[expSrc] = exports[expSrc] || {}; + exports[expSrc] = {...exports[expSrc], ...exportInfo}; + } + }, + + // 退出节点 + exit(path) { + let {node} = path; + if (node._scope) { + scope = scope.parent; + } + }, + }); + + // console.log(src); + // console.log('imports', imports); + // console.log('exports', exports); + + // import * 和 export * 不包括default + // export * from '' 和 export 本文件冲突,export 本文件优先级更高 + // export * from '' 互相冲突,后export * from '' 优先 + // export {} from '', 从其他文件导出,导出的变量无法在本文件使用 + // export default function(){},导出的函数没有name,不能在本文件使用 + /** + * imports: { + * [路径]: { + * [name]: ImportSpecifier, + * default: ImportDefaultSpecifier, + * *: ImportNamespaceSpecifier + * } + * } + * + * exports: { + * [本文件路径]: { + * // export function(){} + * [name]: FunctionDeclaration|VariableDeclaration|ClassDeclaration + * // export default function(){} | export default{} | export {a as default} | export default a + * default: ExportDefaultDeclaration | ExportSpecifier, + * // export {a as aaa,b,c} + * [name]: ExportSpecifier + * }, + * [其他路径]: { + * // export {a as aaa,b,c} from '' | export * as all from '' + * [name]: ExportSpecifier + * // export {default} from '' | export {a as default} from '' | export * as default from '' + * default: ExportSpecifier, + * // export * from '' + * *: ExportAllDeclaration + * }, + * } + */ + + let dep = { + src, + code, + ast, + imports, + exports, + children: [], + scope, + }; + + Object.keys(dep.imports).forEach((childSrc, index) => { + dep.children.push(this.analysis(childSrc)); + }); + + // export {} from './a' a 文件也是子节点 + Object.keys(dep.exports).forEach((childSrc, index) => { + if (childSrc !== src) { + dep.children.push(this.analysis(childSrc)); + } + }); + + return dep; + } +} + +module.exports = { + Graph, +}; diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index 71559b4a..03859a2f 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -1,278 +1,24 @@ -let fs = require('fs'); let path = require('path'); -let mkdirp = require('mkdirp'); -const {parse} = require('@babel/parser'); const traverse = require('@babel/traverse').default; const generate = require('@babel/generator').default; -const t = require('@babel/types'); - -function readFile(p) { - let rst = ''; - p = typeof p === 'object' ? path.join(p.dir, p.base) : p; - try { - rst = fs.readFileSync(p, 'utf-8'); - } catch (e) { - rst = null; - } - return rst; -} +let {writeFile} = require('./util'); +let {Graph} = require('./graph'); -function writeFile(p, data) { - let opath = typeof p === 'string' ? path.parse(p) : p; - mkdirp.sync(opath.dir); - fs.writeFileSync(p, data); -} +function collectReferences(dep) { + let {ast, scope} = dep; -class Scope { - constructor(options) { - options = options || {}; - - this.parent = options.parent; - this.depth = this.parent ? this.parent.depth + 1 : 0; - this.names = options.params || []; - this.nodes = {}; - this.isBlockScope = !!options.block; - this.children = []; - if (this.parent) { - this.parent.children.push(this); - } - } - // 添加变量名 - // isBlockDeclaration 是否是块级声明:let const class import - add(node, name, isBlockDeclaration) { - if (!isBlockDeclaration && this.isBlockScope) { - // it's a `var` or function declaration, and this - // is a block scope, so we need to go up - this.parent.add(node, name, isBlockDeclaration); - } else { - this.names.push(name); - // 变量名可能重复,两个var声明同一变量 - if (this.nodes[name]) { - this.nodes[name].push(node); - } else { - this.nodes[name] = [node]; - } - } - } - - contains(name) { - return !!this.findDefiningScope(name); - } - - findDefiningScope(name) { - if (this.names.includes(name)) { - return this; - } - - if (this.parent) { - return this.parent.findDefiningScope(name); - } - - return null; - } -} - -class Graph { - constructor(entrySrc) { - this.entrySrc = entrySrc; - this.root = this.analysis(entrySrc); - } - - getAbsolutePath(baseSrc, relativeSrc) { - return path.resolve(path.dirname(baseSrc), relativeSrc); - } - - getExpSrc(node, src) { - let expSrc = ''; - - if (node.source) { - expSrc = this.getAbsolutePath(src, node.source.value + '.js'); - } else { - expSrc = src; - } - - return expSrc; - } - - markShakingFlag(node) { - node._shake = 1; - } - - analysis(src) { - let imports = {}; - let exports = {}; - let code = readFile(src); - let ast = parse(code, { - sourceType: 'unambiguous', - plugins: ['classProperties'], - }); - - let scope = new Scope(); - function addToScope(node, attr, isBlockDeclaration = false) { - let identifierNode = node[attr]; - - // 类似于export default function(){} - if (!identifierNode || !identifierNode.name) { - return; - } - - identifierNode._skip = true; - - node._usedByNodes = []; - scope.add(node, identifierNode.name, isBlockDeclaration); - } - - traverse(ast, { - enter: (path) => { - let {node} = path; - let childScope; - switch (node.type) { - // 函数声明 function a(){} - case 'FunctionDeclaration': - childScope = new Scope({ - parent: scope, - block: false, - }); - addToScope(node, 'id', false); - // 箭头函数 ()=>{} - case 'ArrowFunctionExpression': - // 函数表达式 function(){} - case 'FunctionExpression': - childScope = new Scope({ - parent: scope, - block: false, - }); - break; - // 块级作用域{} - case 'BlockStatement': - childScope = new Scope({ - parent: scope, - block: true, - }); - break; - // 变量声明 - case 'VariableDeclaration': - node.declarations.forEach((variableDeclarator) => { - if (node.kind === 'let' || node.kind === 'const') { - addToScope(variableDeclarator, 'id', true); - } else { - addToScope(variableDeclarator, 'id', false); - } - }); - break; - // 类的声明 - case 'ClassDeclaration': - addToScope(node, 'id', true); - break; - // import 的声明 - case 'ImportDeclaration': - node.specifiers.forEach((specifier) => { - addToScope(specifier, 'local', true); - }); - - let impSrc = this.getAbsolutePath( - src, - node.source.value + '.js' - ); - imports[impSrc] = imports[impSrc] || {}; - node.specifiers.forEach((specifier) => { - let name = - specifier.imported && specifier.imported.name; - if (!name) { - if ( - specifier.type === 'ImportDefaultSpecifier' - ) { - name = 'default'; - } else if ( - specifier.type === - 'ImportNamespaceSpecifier' - ) { - name = '*'; - } - } - imports[impSrc][name] = specifier; - }); - break; - // export 的声明 - case 'ExportNamedDeclaration': - let expSrc = this.getExpSrc(node, src); - - exports[expSrc] = exports[expSrc] || {}; - - if (node.specifiers && node.specifiers.length) { - node.specifiers.forEach((specifier) => { - let name = specifier.exported.name; - exports[expSrc][name] = specifier; - this.markShakingFlag(specifier); - }); - } else { - let declaration = node.declaration; - - if (declaration.type === 'FunctionDeclaration') { - let name = declaration.id.name; - exports[expSrc][name] = declaration; - declaration._shake = 1; - this.markShakingFlag(declaration); - } else if ( - declaration.type === 'VariableDeclaration' - ) { - declaration.declarations.forEach( - (variableDeclarator) => { - let name = variableDeclarator.id.name; - exports[expSrc][name] = - variableDeclarator; - this.markShakingFlag( - variableDeclarator - ); - } - ); - } else if ( - declaration.type === 'ClassDeclaration' - ) { - let name = declaration.id.name; - exports[expSrc][name] = declaration; - this.markShakingFlag(declaration); - } - } - break; - case 'ExportDefaultDeclaration': - exports[src] = exports[src] || {}; - exports[src].default = node; - this.markShakingFlag(node); - break; - case 'ExportAllDeclaration': - let exportSrc = this.getExpSrc(node, src); - exports[exportSrc] = exports[exportSrc] || {}; - exports[exportSrc]['*'] = node; - this.markShakingFlag(node); - break; - } - - if (childScope) { - node._scope = childScope; - scope = childScope; - } - }, - - // 退出节点 - exit(path) { - let {node} = path; - if (node._scope) { - scope = scope.parent; - } - }, - }); - - function findScope(node) { - let defineScope = scope.findDefiningScope(node.name); - if (defineScope) { - defineScope.nodes[node.name].forEach((declarationNode) => { - declarationNode._usedByNodes.push(node); - }); - } + let findScope = (node) => { + let defineScope = scope.findDefiningScope(node.name); + if (defineScope) { + defineScope.nodes[node.name].forEach((declarationNode) => { + // 该声明语句被哪些identifier节点使用过 + declarationNode._usedByNodes.push(node); + }); } + }; + let collect = () => { traverse(ast, { enter: (path) => { let {node} = path; @@ -298,8 +44,6 @@ class Graph { !node.computed && path.skipKey('key'); } else if (node.type === 'Identifier') { // TODO,怎么才算变量已经使用 - // 这里的判断不准确,无法判断类似函数a引用函数b,但a并没有没使用到 - // 这里只会去除掉函数a,去除不了函数b !node._skip && findScope(node); } }, @@ -311,69 +55,15 @@ class Graph { } }, }); + }; - // console.log(src); - // console.log('imports', imports); - // console.log('exports', exports); - - // import * 和 export * 不包括default - // export * from '' 和 export 本文件冲突,export 本文件优先级更高 - // export * from '' 互相冲突,后export * from '' 优先 - // export {} from '', 从其他文件导出,导出的变量无法在本文件使用 - // export default function(){},导出的函数没有name,不能再本文件使用 - /** - * imports: { - * [路径]: { - * [name]: ImportSpecifier, - * default: ImportDefaultSpecifier, - * *: ImportNamespaceSpecifier - * } - * } - * - * exports: { - * [本文件路径]: { - * // export function(){} - * [name]: FunctionDeclaration|VariableDeclaration|ClassDeclaration - * // export default function(){} | export default{} | export {a as default} | export default a - * default: ExportDefaultDeclaration | ExportSpecifier, - * // export {a as aaa,b,c} - * [name]: ExportSpecifier - * }, - * [其他路径]: { - * // export {a as aaa,b,c} from '' | export * as all from '' - * [name]: ExportSpecifier - * // export {default} from '' | export {a as default} from '' | export * as default from '' - * default: ExportSpecifier, - * // export * from '' - * *: ExportAllDeclaration - * }, - * } - */ - - let dep = { - src, - code, - ast, - imports, - exports, - children: [], - scope, - }; - - // TODO,只是imports节点不准确 - // export {} from './a' a 文件也是子节点 - Object.keys(dep.imports).forEach((childSrc, index) => { - dep.children[index] = this.analysis(childSrc); - }); + collect(); - return dep; - } + dep.children.forEach((child) => collectReferences(child)); } /** * export node 有一个_shake标志,如果该export没有被import,或者被import后没有使用,_shake = 1 - * 输出时,判断export node 的_shake,当等于1时,遍历子节点,看是否有声明节点,如果声明节点未被引用才可以shake掉 - * */ function shake(dep) { @@ -388,11 +78,11 @@ function shake(dep) { ); let localExports = null; let externalExports = [...exportsArray]; + if (localIndex !== -1) { localExports = externalExports.splice(localIndex, 1)[0]; } - let hasAll = usedNames.some((name) => name === '*'); let usedExports = {}; let addUsedExport = (src, node) => { usedExports[src] = usedExports[src] || {}; @@ -403,6 +93,9 @@ function shake(dep) { usedExports[src]['*'] = node; } }; + + let hasAll = usedNames.some((name) => name === '*'); + if (hasAll) { let hasDefalut = usedNames.some((name) => name === 'default'); let markedDefalut = false; @@ -473,8 +166,20 @@ function shake(dep) { } function remove(dep) { - let {ast, scope, code, src, exports} = dep; + let {scope, exports} = dep; let loop = true; + + let markRemoved = (node)=>{ + node._removed = 1; + traverse(node, { + noScope: true, + enter(path) { + let {node} = path; + node._removed = 1; + }, + }); + }; + let doRemove = (scope) => { let {nodes: allNodes} = scope; Object.values(allNodes).forEach((nodes) => { @@ -483,29 +188,14 @@ function remove(dep) { return; } - if (t.isClassDeclaration(node)) { - console.log('--------------'); - console.log(node._usedByNodes[0]); - } - if ( (node._usedByNodes.length === 0 && (node._shake === 1 || node._shake === undefined)) || (node._usedByNodes.length !== 0 && - node._usedByNodes.every( - (node) => node._removed || node._shake === 1 - )) + node._usedByNodes.every((node) => node._removed)) ) { - node._removed = 1; loop = true; - - traverse(node, { - noScope: true, - enter(path) { - let {node} = path; - node._removed = 1; - }, - }); + markRemoved(node); } }); }); @@ -515,26 +205,27 @@ function remove(dep) { }); }; - while (loop) { - Object.entries(exports).forEach(([src, value]) => { - Object.entries(value).forEach(([name, node]) => { - if ( - node._shake === 1 && - (!node._usedByNodes || - (node._usedByNodes && node._usedByNodes.length === 0)) - ) { - traverse(node, { - noScope: true, - enter(path) { - let {node} = path; - node._shake = 1; - }, - }); - } else { - node._shake = 0; - } - }); + /** + * 遍历exports,shake 标志表示该节点是否被外部有效的 import(即import的方法变量被使用过) + * 如果shake=1,表示没有被有效import过 + * _usedByNodes只存在于声明语句上,表示该声明语句被哪些identifier节点使用过。 + * 只有具名导出函数变量(export function(){}),这样的导出节点才会有_usedByNodes + * shake=1且_usedByNodes不存在,表示该export节点即不被外部有效import,也不会被内部使用 + * shake=1且_usedByNodes存在且有值,表示该节点不被外部有效import,但被内部使用 + */ + Object.entries(exports).forEach(([src, value]) => { + Object.entries(value).forEach(([name, node]) => { + if ( + node._shake === 1 && + (!node._usedByNodes || + (node._usedByNodes && node._usedByNodes.length === 0)) + ) { + markRemoved(node); + } }); + }); + + while (loop) { loop = false; doRemove(scope); } @@ -542,22 +233,19 @@ function remove(dep) { dep.children.forEach((child) => remove(child)); } -function run(dep) { +function output(dep) { let {ast, code, src} = dep; traverse(ast, { enter(path) { let {node} = path; - if ( - node._removed === 1 || - (!node._usedByNodes && node._shake === 1) - ) { + if (node._removed === 1) { path.remove(); } }, }); - const output = generate( + const {code: outputCode} = generate( ast, { /* options */ @@ -567,20 +255,21 @@ function run(dep) { writeFile( path.resolve(path.dirname(src), './shaking', path.basename(src)), - output.code + outputCode ); dep.children.forEach((child) => { - run(child); + output(child); }); } console.time('end'); let entrySrc = path.resolve(__dirname, '../../example/index.js'); let graph = new Graph(entrySrc); +collectReferences(graph.root); shake(graph.root); remove(graph.root); -run(graph.root); +output(graph.root); console.timeEnd('end'); // function name(params) { diff --git a/packages/wxa-cli/src/tree-shake/scope.js b/packages/wxa-cli/src/tree-shake/scope.js index e69de29b..3ab6c0df 100644 --- a/packages/wxa-cli/src/tree-shake/scope.js +++ b/packages/wxa-cli/src/tree-shake/scope.js @@ -0,0 +1,53 @@ +class Scope { + constructor(options) { + options = options || {}; + + this.parent = options.parent; + this.depth = this.parent ? this.parent.depth + 1 : 0; + this.names = options.params || []; + this.nodes = {}; + this.isBlockScope = !!options.block; + this.children = []; + + if (this.parent) { + this.parent.children.push(this); + } + } + // 添加变量名 + // isBlockDeclaration 是否是块级声明:let const class import + add(node, name, isBlockDeclaration) { + if (!isBlockDeclaration && this.isBlockScope) { + // it's a `var` or function declaration, and this + // is a block scope, so we need to go up + this.parent.add(node, name, isBlockDeclaration); + } else { + this.names.push(name); + // 变量名可能重复,两个var声明同一变量 + if (this.nodes[name]) { + this.nodes[name].push(node); + } else { + this.nodes[name] = [node]; + } + } + } + + contains(name) { + return !!this.findDefiningScope(name); + } + + findDefiningScope(name) { + if (this.names.includes(name)) { + return this; + } + + if (this.parent) { + return this.parent.findDefiningScope(name); + } + + return null; + } +} + +module.exports = { + Scope, +}; diff --git a/packages/wxa-cli/src/tree-shake/util.js b/packages/wxa-cli/src/tree-shake/util.js new file mode 100644 index 00000000..28e98023 --- /dev/null +++ b/packages/wxa-cli/src/tree-shake/util.js @@ -0,0 +1,26 @@ +let fs = require('fs'); +let path = require('path'); +let mkdirp = require('mkdirp'); + +function readFile(p) { + let rst = ''; + p = typeof p === 'object' ? path.join(p.dir, p.base) : p; + try { + rst = fs.readFileSync(p, 'utf-8'); + } catch (e) { + rst = null; + } + + return rst; +} + +function writeFile(p, data) { + let opath = typeof p === 'string' ? path.parse(p) : p; + mkdirp.sync(opath.dir); + fs.writeFileSync(p, data); +} + +module.exports={ + readFile, + writeFile, +}; From aff257f1dadde126af1bf2f92f6457fe67510109 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Fri, 11 Jun 2021 18:10:57 +0800 Subject: [PATCH 07/20] =?UTF-8?q?feat:=20=E4=BF=AE=E5=A4=8D=E4=B8=80?= =?UTF-8?q?=E4=BA=9Bbugs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/example/expDFOF/a.js | 13 ++ packages/wxa-cli/example/expDFOF/index.js | 25 ++ packages/wxa-cli/example/index.js | 27 +-- packages/wxa-cli/example/shaking/index.js | 9 +- packages/wxa-cli/example/test.js | 58 +++++ packages/wxa-cli/src/tree-shake/graph.js | 270 +++++++++++++--------- packages/wxa-cli/src/tree-shake/index.js | 150 ++++++++---- packages/wxa-cli/src/tree-shake/util.js | 140 ++++++++++- 8 files changed, 514 insertions(+), 178 deletions(-) create mode 100644 packages/wxa-cli/example/expDFOF/a.js create mode 100644 packages/wxa-cli/example/expDFOF/index.js create mode 100644 packages/wxa-cli/example/test.js diff --git a/packages/wxa-cli/example/expDFOF/a.js b/packages/wxa-cli/example/expDFOF/a.js new file mode 100644 index 00000000..23a0ce7e --- /dev/null +++ b/packages/wxa-cli/example/expDFOF/a.js @@ -0,0 +1,13 @@ +let num1 = 1; +let num2 = 2; +let obj1 ={ + x: 1, +}; + +function name(params) { + +} + +export default { + +}; diff --git a/packages/wxa-cli/example/expDFOF/index.js b/packages/wxa-cli/example/expDFOF/index.js new file mode 100644 index 00000000..47ab447c --- /dev/null +++ b/packages/wxa-cli/example/expDFOF/index.js @@ -0,0 +1,25 @@ + + +export {default} from './a'; + + +/* eslint-disable one-var */ +// 具名导出 +export {a as aa, b, c} from ''; +export * as all from ''; +export function fn1() {} +let o1 = 1, o2=3; +export {o1 as o11, o2}; + +// 默认导出 +// export {default} from '' +// export {a as default} from '' +// export * as default from '' +// export default function() {} +// export default {} +// export {a as default} +// let p1 = 1 +// export default p1 + +// 导出全部 +export * from ''; diff --git a/packages/wxa-cli/example/index.js b/packages/wxa-cli/example/index.js index 9b1b41be..a45ebb81 100644 --- a/packages/wxa-cli/example/index.js +++ b/packages/wxa-cli/example/index.js @@ -2,7 +2,6 @@ import getMyUser, {getName as getMyName} from './user'; import * as user from './user'; - console.log(user); let a = {x: 1}, n = 1; @@ -11,7 +10,7 @@ function m(x = 1, y) { a = 5; ++a; t = 9; - t+5; + t + 5; let qqq = 10; } m(); @@ -22,24 +21,18 @@ let sss = (a, b) => {}; [1, 2, 3].forEach(function(item) {}); -{ -} - for (i = 0; i < 100; i++) {} class Myclass { - [n]=1; - [n]=()=>{ - - } + [n] = 1; + [n] = () => {}; } export function mm() {} mm(); - function name(params) { let t = {q: 1}; let q = 2; @@ -54,7 +47,6 @@ let obj = { (function(x, y) {})(); - getName(); // export default { // x: 1, @@ -64,9 +56,7 @@ getName(); // age, // }; export * from './user'; -export function getName() { - -} +export function getName() {} // export {m as qqqqq, a as default}; // export {x, y} from './a'; @@ -76,13 +66,8 @@ export default function() {} export {Myclass}; // eslint-disable-next-line no-var -export { - mm as ttttttt, -}; +export {mm as ttttttt}; export {getName as tttt} from './user'; - -export * as tttttt from 'user'; - - +export * as tttttt from './user'; diff --git a/packages/wxa-cli/example/shaking/index.js b/packages/wxa-cli/example/shaking/index.js index b64b1d09..e7adcf9b 100644 --- a/packages/wxa-cli/example/shaking/index.js +++ b/packages/wxa-cli/example/shaking/index.js @@ -3,7 +3,7 @@ import './user'; import * as user from './user'; console.log(user); let a = { - x: 1, + x: 1 }; let t = 10; @@ -15,15 +15,14 @@ function m(x = 1, y) { } m(); -[1, 2, 3].forEach(function(item) {}); -{} +[1, 2, 3].forEach(function (item) {}); for (i = 0; i < 100; i++) {} export function mm() {} mm(); -(function(x, y) {})(); +(function (x, y) {})(); getName(); // export default { // x: 1, @@ -40,4 +39,4 @@ export {}; // eslint-disable-next-line no-var export {}; export {} from './user'; -export {} from 'user'; +export {} from './user'; \ No newline at end of file diff --git a/packages/wxa-cli/example/test.js b/packages/wxa-cli/example/test.js new file mode 100644 index 00000000..d88b550f --- /dev/null +++ b/packages/wxa-cli/example/test.js @@ -0,0 +1,58 @@ +/* eslint-disable one-var */ + +let obj = {x: 1}, + num1 = 1; +let num2 = 10; +let str1 = 'a'; +function m() { + num1 = 5; + ++num2; + let qqq = 10; +} + +m(); + +let fn1 = function() {}; + +let fn2 = () => {}; + +[1, 2, 3].forEach(function(item) {}); + +for (i = 0; i < 100; i++) {} + +class Myclass { + [str1] = 1; + [str1] = () => {}; +} + + +m(); + +function name(params) { + let t = {q: 1}; + let q = 2; + q++; + t.q; +} + + +(function(x, y) {})(); + +getName(); +// export default { +// x: 1, +// t() { +// }, +// m, +// age, +// }; +export * from './user'; +export function getName() {} +// export {m as qqqqq, a as default}; + +// export {x, y} from './a'; + +export default function() {} + +export {Myclass}; +// eslint-disable-next-line no-var diff --git a/packages/wxa-cli/src/tree-shake/graph.js b/packages/wxa-cli/src/tree-shake/graph.js index 7ebbe529..9296547a 100644 --- a/packages/wxa-cli/src/tree-shake/graph.js +++ b/packages/wxa-cli/src/tree-shake/graph.js @@ -1,24 +1,36 @@ -const path = require('path'); -const {parse} = require('@babel/parser'); const traverse = require('@babel/traverse').default; const {Scope} = require('./scope'); -const {readFile} = require('./util'); +const {readFile, resolveDepSrc, parseESCode} = require('./util'); class Graph { - constructor(entrySrc) { - this.entrySrc = entrySrc; - this.root = this.analysis(entrySrc); + constructor(entries) { + this.entries = entries; + this.analysis(); } - getAbsolutePath(baseSrc, relativeSrc) { - return path.resolve(path.dirname(baseSrc), relativeSrc); + getAbsolutePath(fileSrc, depSrc) { + let s = resolveDepSrc({ + fileSrc, + depSrc, + root: 'src', + alias: {'@': 'src'}, + }); + + if (!s.endsWith('.js')) { + s += '.js'; + } + + // console.log('--------'); + // console.log(s); + + return s; } getExpSrc(node, src) { let expSrc = ''; if (node.source) { - expSrc = this.getAbsolutePath(src, node.source.value + '.js'); + expSrc = this.getAbsolutePath(src, node.source.value); } else { expSrc = src; } @@ -120,12 +132,16 @@ class Graph { return importInfo; } - collectExport(path) { + collectExport(path, isRoot) { let {node} = path; let exportInfo = null; let markShakingFlag = (node) => { - node._shake = 1; + if (isRoot) { + node._shake = 0; + } else { + node._shake = 1; + } }; switch (node.type) { @@ -163,8 +179,15 @@ class Graph { break; case 'ExportDefaultDeclaration': exportInfo = {}; - exportInfo.default = node; - markShakingFlag(node); + let declaration = node.declaration; + + if (declaration) { + exportInfo.default = declaration; + } else { + exportInfo.default = node; + } + + markShakingFlag(exportInfo.default); break; case 'ExportAllDeclaration': exportInfo = {}; @@ -176,114 +199,141 @@ class Graph { return exportInfo; } - analysis(src) { - let imports = {}; - let exports = {}; - let code = readFile(src); - let ast = parse(code, { - sourceType: 'unambiguous', - plugins: ['classProperties'], - }); + analysis() { + let analyzedFile = {}; - let scope = new Scope(); + let doAnalysis = (entry, isRoot) => { + let src = ''; + let content = ''; - traverse(ast, { - enter: (path) => { - let {node} = path; + if (typeof entry === 'string') { + src = entry; + } else { + src = entry.src; + content = entry.content; + } - let childScope = this.collectDeclaration(path, scope); - if (childScope) { - node._scope = childScope; - scope = childScope; - } + // if (src.endsWith('safe-area-inset\\index.js')) { + // console.log('src', src); + // } - let importInfo = this.collectImport(path); - if (importInfo) { - let impSrc = this.getAbsolutePath( - src, - node.source.value + '.js' - ); - imports[impSrc] = imports[impSrc] || {}; - imports[impSrc] = {...imports[impSrc], ...importInfo}; - } + if (analyzedFile[src]) { + return analyzedFile[src]; + } - let exportInfo = this.collectExport(path); - if (exportInfo) { - let expSrc = this.getExpSrc(node, src); - exports[expSrc] = exports[expSrc] || {}; - exports[expSrc] = {...exports[expSrc], ...exportInfo}; - } - }, + let imports = {}; + let exports = {}; + let code = content || readFile(src); + let ast = parseESCode(code); - // 退出节点 - exit(path) { - let {node} = path; - if (node._scope) { - scope = scope.parent; + let scope = new Scope(); + + traverse(ast, { + enter: (path) => { + let {node} = path; + + let childScope = this.collectDeclaration(path, scope); + if (childScope) { + node._scope = childScope; + scope = childScope; + } + + let importInfo = this.collectImport(path); + if (importInfo) { + let impSrc = this.getAbsolutePath( + src, + node.source.value + ); + imports[impSrc] = imports[impSrc] || {}; + imports[impSrc] = {...imports[impSrc], ...importInfo}; + } + + let exportInfo = this.collectExport(path, isRoot); + if (exportInfo) { + let expSrc = this.getExpSrc(node, src); + exports[expSrc] = exports[expSrc] || {}; + exports[expSrc] = {...exports[expSrc], ...exportInfo}; + } + }, + + // 退出节点 + exit(path) { + let {node} = path; + if (node._scope) { + scope = scope.parent; + } + }, + }); + + // console.log(src); + // console.log('imports', imports); + // console.log('exports', exports); + + // import * 和 export * 不包括default + // export * from '' 和 export 本文件冲突,export 本文件优先级更高 + // export * from '' 互相冲突,后export * from '' 优先 + // export {} from '', 从其他文件导出,导出的变量无法在本文件使用 + // export default function(){},导出的函数没有name时,不能在本文件使用 + // 不存在语法 export default let a =1 + /** + * imports: { + * [路径]: { + * [name]: ImportSpecifier, + * default: ImportDefaultSpecifier, + * *: ImportNamespaceSpecifier + * } + * } + * + * exports: { + * [本文件路径]: { + * // export function(){} + * [name]: FunctionDeclaration|VariableDeclaration|ClassDeclaration + * // export default function(){} | export default{} | export {a as default} | export default a + * default: ExportDefaultDeclaration | FunctionDeclaration | ClassDeclaration |ExportSpecifier, + * // export {a as aaa,b,c} + * [name]: ExportSpecifier + * }, + * [其他路径]: { + * // export {a as aaa,b,c} from '' | export * as all from '' + * [name]: ExportSpecifier + * // export {default} from '' | export {a as default} from '' | export * as default from '' + * default: ExportSpecifier, + * // export * from '' + * *: ExportAllDeclaration + * }, + * } + */ + + let dep = { + src, + code, + ast, + imports, + exports, + children: [], + scope, + isRoot, + }; + + analyzedFile[src] = dep; + + Object.keys(dep.imports).forEach((childSrc, index) => { + dep.children.push(doAnalysis(childSrc)); + }); + + // export {} from './a' a 文件也是子节点 + Object.keys(dep.exports).forEach((childSrc) => { + if (childSrc !== src) { + dep.children.push(doAnalysis(childSrc)); } - }, - }); + }); - // console.log(src); - // console.log('imports', imports); - // console.log('exports', exports); - - // import * 和 export * 不包括default - // export * from '' 和 export 本文件冲突,export 本文件优先级更高 - // export * from '' 互相冲突,后export * from '' 优先 - // export {} from '', 从其他文件导出,导出的变量无法在本文件使用 - // export default function(){},导出的函数没有name,不能在本文件使用 - /** - * imports: { - * [路径]: { - * [name]: ImportSpecifier, - * default: ImportDefaultSpecifier, - * *: ImportNamespaceSpecifier - * } - * } - * - * exports: { - * [本文件路径]: { - * // export function(){} - * [name]: FunctionDeclaration|VariableDeclaration|ClassDeclaration - * // export default function(){} | export default{} | export {a as default} | export default a - * default: ExportDefaultDeclaration | ExportSpecifier, - * // export {a as aaa,b,c} - * [name]: ExportSpecifier - * }, - * [其他路径]: { - * // export {a as aaa,b,c} from '' | export * as all from '' - * [name]: ExportSpecifier - * // export {default} from '' | export {a as default} from '' | export * as default from '' - * default: ExportSpecifier, - * // export * from '' - * *: ExportAllDeclaration - * }, - * } - */ - - let dep = { - src, - code, - ast, - imports, - exports, - children: [], - scope, + return dep; }; - Object.keys(dep.imports).forEach((childSrc, index) => { - dep.children.push(this.analysis(childSrc)); + this.roots = this.entries.map((entry) => { + return doAnalysis(entry, true); }); - - // export {} from './a' a 文件也是子节点 - Object.keys(dep.exports).forEach((childSrc, index) => { - if (childSrc !== src) { - dep.children.push(this.analysis(childSrc)); - } - }); - - return dep; } } diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index 03859a2f..bcb061a3 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -1,4 +1,3 @@ -let path = require('path'); const traverse = require('@babel/traverse').default; const generate = require('@babel/generator').default; @@ -6,6 +5,10 @@ let {writeFile} = require('./util'); let {Graph} = require('./graph'); function collectReferences(dep) { + if (dep._collcted) { + return; + } + let {ast, scope} = dep; let findScope = (node) => { @@ -29,7 +32,7 @@ function collectReferences(dep) { // obj.x 类型的属性访问,不算对x变量的使用 if (node.type === 'MemberExpression') { - !node.computed && path.skip(); + !node.computed && path.skipKey('property'); } else if (node.type === 'ObjectProperty') { // {x:1} 对象属性 !node.computed && path.skipKey('key'); @@ -58,15 +61,22 @@ function collectReferences(dep) { }; collect(); + dep._collcted = true; dep.children.forEach((child) => collectReferences(child)); } /** * export node 有一个_shake标志,如果该export没有被import,或者被import后没有使用,_shake = 1 + * 在这里,遍历全局文件树,根据import和export关系,对没使用的export进行标记 + * 但如果用require去引入一个export函数变量,这里并不能分析到这个export函数变量被使用过(所以不能去 require 一个 export) */ function shake(dep) { + if (dep._shook) { + return; + } + let imports = dep.imports; let mark = (dep, usedNames, childSrc) => { @@ -120,8 +130,10 @@ function shake(dep) { !markedDefalut) || name !== 'default' ) { - node._shake = 0; - addUsedExport(src, node); + if (node._shake === 1) { + node._shake = 0; + addUsedExport(src, node); + } } }); }); @@ -138,20 +150,26 @@ function shake(dep) { externalExports.forEach(([src, value]) => { let node = value[name] || value['*']; if (node) { - node._shake = 0; - addUsedExport(src, node); + if (node._shake === 1) { + node._shake = 0; + addUsedExport(src, node); + } } }); }); } + if (childSrc.endsWith('store\\configure.js')) { + console.log('1111'); + } + Object.entries(usedExports).forEach((src, value) => { mark(child, Object.keys(value), src); }); } }; - Object.entries(imports).forEach(([src, value], index) => { + Object.entries(imports).forEach(([src, value]) => { let usedNames = []; Object.entries(value).forEach(([name, node]) => { @@ -162,14 +180,20 @@ function shake(dep) { mark(dep, usedNames, src); }); + dep._shook = true; + dep.children.forEach((child) => shake(child)); } function remove(dep) { + if (dep._removed) { + return; + } + let {scope, exports} = dep; let loop = true; - let markRemoved = (node)=>{ + let markRemoved = (node) => { node._removed = 1; traverse(node, { noScope: true, @@ -209,7 +233,8 @@ function remove(dep) { * 遍历exports,shake 标志表示该节点是否被外部有效的 import(即import的方法变量被使用过) * 如果shake=1,表示没有被有效import过 * _usedByNodes只存在于声明语句上,表示该声明语句被哪些identifier节点使用过。 - * 只有具名导出函数变量(export function(){}),这样的导出节点才会有_usedByNodes + * 在导出语句中: + * 只有类似有name的函数变量(export function a(){} export default function a(){}),这样的导出节点才会有_usedByNodes * shake=1且_usedByNodes不存在,表示该export节点即不被外部有效import,也不会被内部使用 * shake=1且_usedByNodes存在且有值,表示该节点不被外部有效import,但被内部使用 */ @@ -221,7 +246,7 @@ function remove(dep) { (node._usedByNodes && node._usedByNodes.length === 0)) ) { markRemoved(node); - } + } }); }); @@ -230,47 +255,90 @@ function remove(dep) { doRemove(scope); } + dep._removed = true; + dep.children.forEach((child) => remove(child)); } function output(dep) { - let {ast, code, src} = dep; + let contents = {}; - traverse(ast, { - enter(path) { - let {node} = path; - if (node._removed === 1) { - path.remove(); - } - }, + let run = (dep) => { + let {ast, code, src} = dep; + + if (dep._output) { + return; + } + + traverse(ast, { + enter(path) { + let {node} = path; + if (node._removed === 1) { + path.remove(); + } + }, + }); + + const {code: outputCode} = generate( + ast, + { + /* options */ + decoratorsBeforeExport: true, + }, + code + ); + + // writeFile( + // path.resolve(path.dirname(src), './shaking', path.basename(src)), + // outputCode + // ); + + contents[src] = outputCode; + + dep._output = true; + + dep.children.forEach((child) => { + run(child); + }); + }; + + run(dep); + + return contents; +} + +function start(entries) { + let graph = new Graph(entries); + + graph.roots.forEach((root) => { + collectReferences(root); }); - const {code: outputCode} = generate( - ast, - { - /* options */ - }, - code - ); - - writeFile( - path.resolve(path.dirname(src), './shaking', path.basename(src)), - outputCode - ); - - dep.children.forEach((child) => { - output(child); + console.log('collected'); + + graph.roots.forEach((root) => { + shake(root); }); + + console.log('shook'); + + let contents = {}; + graph.roots.forEach((root) => { + remove(root); + contents = {...contents, ...output(root)}; + }); + + return contents; } -console.time('end'); -let entrySrc = path.resolve(__dirname, '../../example/index.js'); -let graph = new Graph(entrySrc); -collectReferences(graph.root); -shake(graph.root); -remove(graph.root); -output(graph.root); -console.timeEnd('end'); +module.exports = { + start, +}; + +// console.time('end'); +// let entrySrc = path.resolve(__dirname, '../../example/index.js'); +// start([entrySrc]); +// console.timeEnd('end'); // function name(params) { // console.log(m); diff --git a/packages/wxa-cli/src/tree-shake/util.js b/packages/wxa-cli/src/tree-shake/util.js index 28e98023..c55305d9 100644 --- a/packages/wxa-cli/src/tree-shake/util.js +++ b/packages/wxa-cli/src/tree-shake/util.js @@ -1,6 +1,8 @@ let fs = require('fs'); let path = require('path'); let mkdirp = require('mkdirp'); +const {parse} = require('@babel/parser'); +let findRoot = require('find-root'); function readFile(p) { let rst = ''; @@ -20,7 +22,143 @@ function writeFile(p, data) { fs.writeFileSync(p, data); } -module.exports={ +function isFile(p) { + p = typeof p === 'object' ? path.join(p.dir, p.base) : p; + if (!fs.existsSync(p)) return false; + return fs.statSync(p).isFile(); +} + +function isDir(p) { + // console.log(isDir, fs.existsSync(p), p); + if (!fs.existsSync(p)) { + return false; + } + + return fs.statSync(p).isDirectory(); +} + +function getPkgConfig(npmSrc, lib) { + let uri = path.join(npmSrc, lib); + let location = findRoot(uri); + let content = readFile(path.join(location, 'package.json')); + try { + content = JSON.parse(content); + } catch (e) { + content = null; + } + + return content; +} + +/** + * import路径: + * "./a", "a", "@/a", "/a" + * + */ + +let cwd = process.cwd(); +function resolveDepSrc({fileSrc, depSrc, root, alias}) { + let getDepAbsoulte = (src) => { + if (isDir(src)) { + return path.join(src, 'index.js'); + } + + if (!src.endsWith('.js')) { + return src + '.js'; + } + + return src; + }; + + if (alias) { + let aliasNames = Object.keys(alias); + let absoluteSrc = ''; + let matched = aliasNames.some((aliasName) => { + if (depSrc.startsWith(aliasName + '/')) { + let aliasSrc = alias[aliasName]; + + absoluteSrc = path.resolve( + cwd, + aliasSrc, + depSrc.replace(aliasName, '.') + ); + return true; + } + }); + + if (matched) { + return getDepAbsoulte(absoluteSrc); + } + } + + if (depSrc.startsWith('/')) { + return getDepAbsoulte(path.resolve(cwd, root, depSrc.replace('/', ''))); + } + + if (depSrc.startsWith('./') || depSrc.startsWith('../')) { + let fileDir = path.dirname(fileSrc); + return getDepAbsoulte(path.resolve(fileDir, depSrc)); + } + + let npmSrc = path.join(cwd, 'node_modules'); + let absoluteSrc = path.join(npmSrc, depSrc); + + if (!absoluteSrc.endsWith('.js')) { + absoluteSrc += '.js'; + } + + if (isFile(absoluteSrc)) { + return absoluteSrc; + } + + let pkg = getPkgConfig(npmSrc, depSrc); + + if (!pkg) { + throw new Error('找不到模块' + depSrc); + } + + let main = pkg.main || 'index.js'; + // 优先使用依赖的 browser 版本 + if (pkg.browser && typeof pkg.browser === 'string') { + main = pkg.browser; + } + + return getDepAbsoulte(path.join(npmSrc, depSrc, main)); +} + +function parseESCode(code, plugins = [], options) { + plugins = [ + ['decorators', {decoratorsBeforeExport: true}], + 'classProperties', + 'jsx', + 'typescript', + 'exportNamespaceFrom', + 'exportDefaultFrom', + 'objectRestSpread', + ...plugins, + ]; + + return parse(code, { + plugins, + sourceType: 'unambiguous', + ...options, + }); +} + +// console.log( +// resolveDepSrc({ +// fileSrc: path.join(cwd, './src/a.js'), +// depSrc: '@/b', +// root: 'src', +// alias: { +// '@': path.join(cwd, '/src/xxx'), +// }, +// }) +// ); + +module.exports = { readFile, writeFile, + resolveDepSrc, + parseESCode, }; From 3fab4b387ad0db508e813e188567563448850ce3 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Mon, 14 Jun 2021 22:54:43 +0800 Subject: [PATCH 08/20] =?UTF-8?q?feat:=20commonjs=20=E8=BD=AC=20es6=20?= =?UTF-8?q?=E5=B0=9D=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/package-lock.json | 1040 ++--------------- packages/wxa-cli/package.json | 1 + packages/wxa-cli/src/tree-shake/index.js | 1 - .../src/tree-shake/tansform-commonJS.js | 454 +++++++ .../src/tree-shake/transform-test-a.js | 245 ++++ .../wxa-cli/src/tree-shake/transform-test.js | 233 ++++ 6 files changed, 1035 insertions(+), 939 deletions(-) create mode 100644 packages/wxa-cli/src/tree-shake/tansform-commonJS.js create mode 100644 packages/wxa-cli/src/tree-shake/transform-test-a.js create mode 100644 packages/wxa-cli/src/tree-shake/transform-test.js diff --git a/packages/wxa-cli/package-lock.json b/packages/wxa-cli/package-lock.json index c8db8e75..80d54fab 100644 --- a/packages/wxa-cli/package-lock.json +++ b/packages/wxa-cli/package-lock.json @@ -1,6 +1,6 @@ { "name": "@wxa/cli2", - "version": "2.2.15", + "version": "2.2.16", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -237,6 +237,7 @@ "version": "7.11.6", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==", + "dev": true, "requires": { "@babel/code-frame": "^7.10.4", "@babel/generator": "^7.11.6", @@ -260,6 +261,7 @@ "version": "7.11.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", + "dev": true, "requires": { "@babel/code-frame": "^7.10.4", "@babel/generator": "^7.11.5", @@ -276,6 +278,7 @@ "version": "7.11.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", "lodash": "^4.17.19", @@ -286,6 +289,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, "requires": { "ms": "^2.1.1" } @@ -780,6 +784,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", + "dev": true, "requires": { "@babel/template": "^7.10.4", "@babel/traverse": "^7.10.4", @@ -790,6 +795,7 @@ "version": "7.11.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", + "dev": true, "requires": { "@babel/code-frame": "^7.10.4", "@babel/generator": "^7.11.5", @@ -806,6 +812,7 @@ "version": "7.11.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", "lodash": "^4.17.19", @@ -816,6 +823,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, "requires": { "ms": "^2.1.1" } @@ -1737,46 +1745,6 @@ "@xtuc/long": "4.2.2" } }, - "@wxa/compiler-babel": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@wxa/compiler-babel/-/compiler-babel-2.2.0.tgz", - "integrity": "sha512-kjQL/T0vLdulAoaCVzlmAE3UbtC1e/c6JVmf/OL9hi7oDspAhlyHSySOH9JhTGYzOKPYbJpBrO1EoMMsnLWRMA==", - "requires": { - "@babel/core": "^7.1.0", - "debug": "^4.0.1", - "find-cache-dir": "^2.0.0", - "mkdirp": "^0.5.1", - "zlib": "^1.0.5" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - } - } - }, - "@wxa/compiler-sass": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@wxa/compiler-sass/-/compiler-sass-2.2.0.tgz", - "integrity": "sha512-te92dBDbVQDMaqaTopmK9pIx8W2WWg3bESVv4T71WS4UHLzy3boqnjICS5w4ZfCHpeL4imvMiAVZe37tHcT3Jw==", - "requires": { - "node-sass": "^4.12.0" - } - }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -1789,11 +1757,6 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, "acorn": { "version": "5.7.4", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", @@ -1821,6 +1784,7 @@ "version": "6.12.4", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1840,11 +1804,6 @@ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", "dev": true }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" - }, "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", @@ -1853,7 +1812,8 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true }, "ansi-styles": { "version": "3.2.1", @@ -1875,16 +1835,8 @@ "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true }, "argparse": { "version": "1.0.10", @@ -1910,11 +1862,6 @@ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" - }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -1938,14 +1885,6 @@ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, "asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -1993,11 +1932,6 @@ } } }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -2010,31 +1944,11 @@ "dev": true, "optional": true }, - "async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==" - }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -2162,14 +2076,6 @@ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", "dev": true }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -2191,14 +2097,6 @@ "file-uri-to-path": "1.0.0" } }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "requires": { - "inherits": "~2.0.0" - } - }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -2450,30 +2348,11 @@ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "dev": true }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, "caniuse-lite": { "version": "1.0.30001125", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001125.tgz", "integrity": "sha512-9f+r7BW8Qli917mU3j0fUaTweT3f3vnX/Lcs+1C73V+RADmFme+Ih0Br8vONQi3X0lseOe6ZHfsZLCA8MSjxUA==" }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -2573,6 +2452,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, "requires": { "string-width": "^3.1.0", "strip-ansi": "^5.2.0", @@ -2582,17 +2462,20 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -2603,6 +2486,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -2615,11 +2499,6 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -2642,14 +2521,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -2688,11 +2559,6 @@ "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", "dev": true }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, "constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", @@ -2703,6 +2569,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, "requires": { "safe-buffer": "~5.1.1" } @@ -2750,7 +2617,8 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "create-ecdh": { "version": "4.0.4", @@ -2797,15 +2665,6 @@ "sha.js": "^2.4.8" } }, - "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -2825,28 +2684,12 @@ "randomfill": "^1.0.3" } }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "requires": { - "array-find-index": "^1.0.1" - } - }, "cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -2858,7 +2701,8 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true }, "decode-uri-component": { "version": "0.2.0", @@ -2921,16 +2765,6 @@ } } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, "des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -3048,15 +2882,6 @@ "stream-shift": "^1.0.0" } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "electron-to-chromium": { "version": "1.3.564", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.564.tgz", @@ -3088,7 +2913,8 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true }, "emojis-list": { "version": "3.0.0", @@ -3142,14 +2968,6 @@ "prr": "~1.0.1" } }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, "es-abstract": { "version": "1.17.6", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", @@ -3494,11 +3312,6 @@ "homedir-polyfill": "^1.0.1" } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", @@ -3587,15 +3400,11 @@ } } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "fast-glob": { "version": "2.2.7", @@ -3634,7 +3443,8 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -3761,6 +3571,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -3815,21 +3626,6 @@ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -3877,17 +3673,6 @@ "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", "optional": true }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -3899,57 +3684,23 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "requires": { - "globule": "^1.0.0" - } - }, "gensync": { "version": "1.0.0-beta.1", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -4037,40 +3788,17 @@ } } }, - "globule": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", - "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - } - }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true }, "growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -4083,6 +3811,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4097,11 +3826,6 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -4209,11 +3933,6 @@ "parse-passwd": "^1.0.0" } }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" - }, "htmlparser2": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", @@ -4239,16 +3958,6 @@ } } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -4296,19 +4005,6 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, - "in-publish": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", - "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==" - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "requires": { - "repeating": "^2.0.0" - } - }, "infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", @@ -4432,11 +4128,6 @@ } } }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -4505,19 +4196,6 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -4561,16 +4239,6 @@ "has-symbols": "^1.0.1" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -4596,11 +4264,6 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, "js-base64": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", @@ -4621,11 +4284,6 @@ "esprima": "^4.0.0" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -4637,15 +4295,11 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -4653,11 +4307,6 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, "json5": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", @@ -4666,17 +4315,6 @@ "minimist": "^1.2.5" } }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -4705,25 +4343,6 @@ "type-check": "~0.3.2" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -4756,6 +4375,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -4774,19 +4394,11 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -4796,6 +4408,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, "requires": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -4806,11 +4419,6 @@ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" - }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -4840,23 +4448,6 @@ "readable-stream": "^2.0.1" } }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - } - }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4977,19 +4568,6 @@ } } }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "requires": { - "mime-db": "1.44.0" - } - }, "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", @@ -5100,7 +4678,9 @@ "nan": { "version": "2.14.1", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "dev": true, + "optional": true }, "nanomatch": { "version": "1.2.13", @@ -5138,32 +4718,6 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "node-gyp": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" - } - } - }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -5220,103 +4774,16 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==" }, - "node-sass": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", - "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", - "requires": { - "async-foreach": "^0.1.3", - "chalk": "^1.1.1", - "cross-spawn": "^3.0.0", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "in-publish": "^2.0.0", - "lodash": "^4.17.15", - "meow": "^3.7.0", - "mkdirp": "^0.5.1", - "nan": "^2.13.2", - "node-gyp": "^3.8.0", - "npmlog": "^4.0.0", - "request": "^2.88.0", - "sass-graph": "2.2.5", - "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true }, "object-copy": { "version": "0.1.0", @@ -5419,29 +4886,16 @@ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "requires": { "p-try": "^2.0.0" } @@ -5450,6 +4904,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -5457,7 +4912,8 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true }, "pako": { "version": "1.0.11", @@ -5489,14 +4945,6 @@ "safe-buffer": "^5.1.1" } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "^1.2.0" - } - }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -5546,23 +4994,6 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } - } - }, "pbkdf2": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", @@ -5576,11 +5007,6 @@ "sha.js": "^2.4.8" } }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -5589,25 +5015,14 @@ "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" - } + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, "requires": { "find-up": "^3.0.0" } @@ -5671,7 +5086,8 @@ "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true }, "progress": { "version": "2.0.3", @@ -5704,12 +5120,8 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true }, "public-encrypt": { "version": "4.0.3", @@ -5769,12 +5181,8 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "querystring": { "version": "0.2.0", @@ -5807,48 +5215,11 @@ "safe-buffer": "^5.1.0" } }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5875,15 +5246,6 @@ "resolve": "^1.1.6" } }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, "regenerate": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", @@ -5975,50 +5337,17 @@ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true }, "require-uncached": { "version": "1.0.3", @@ -6030,6 +5359,12 @@ "resolve-from": "^1.0.0" } }, + "reserved-words": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/reserved-words/download/reserved-words-0.1.2.tgz", + "integrity": "sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=", + "dev": true + }, "resolve": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", @@ -6107,6 +5442,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, "requires": { "glob": "^7.1.3" } @@ -6176,17 +5512,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "sass-graph": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", - "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", - "requires": { - "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^13.3.2" - } - }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -6206,25 +5531,6 @@ } } }, - "scss-tokenizer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", - "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", - "requires": { - "js-base64": "^2.1.8", - "source-map": "^0.4.2" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -6242,7 +5548,8 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true }, "set-value": { "version": "2.0.1", @@ -6494,34 +5801,6 @@ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -6536,22 +5815,6 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", @@ -6580,14 +5843,6 @@ } } }, - "stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "requires": { - "readable-stream": "^2.0.1" - } - }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -6627,16 +5882,6 @@ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, "string.prototype.trimend": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", @@ -6667,26 +5912,11 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, "requires": { "ansi-regex": "^2.0.0" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "requires": { - "get-stdin": "^4.0.1" - } - }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -6777,16 +6007,6 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, "terser": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", @@ -6928,28 +6148,6 @@ "is-number": "^7.0.0" } }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" - }, - "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "requires": { - "glob": "^7.1.2" - } - }, "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", @@ -6961,19 +6159,6 @@ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -7089,6 +6274,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -7143,11 +6329,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, "v8-compile-cache": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", @@ -7159,25 +6340,6 @@ "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=" }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -7515,15 +6677,8 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "requires": { - "string-width": "^1.0.2 || 2" - } + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true }, "word-wrap": { "version": "1.2.3", @@ -7544,6 +6699,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, "requires": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", @@ -7553,17 +6709,20 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -7574,6 +6733,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -7603,17 +6763,20 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true }, "yargs": { "version": "13.3.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, "requires": { "cliui": "^5.0.0", "find-up": "^3.0.0", @@ -7630,17 +6793,20 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -7651,6 +6817,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -7661,6 +6828,7 @@ "version": "13.1.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -7669,14 +6837,10 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true } } - }, - "zlib": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/zlib/-/zlib-1.0.5.tgz", - "integrity": "sha1-bnyXL8NxxkWmr7A6sUdp3vEU/MA=" } } } diff --git a/packages/wxa-cli/package.json b/packages/wxa-cli/package.json index 839c34ad..a5d39c3a 100644 --- a/packages/wxa-cli/package.json +++ b/packages/wxa-cli/package.json @@ -30,6 +30,7 @@ "babel-eslint": "^9.0.0", "eslint": "^4.15.0", "eslint-config-google": "^0.9.1", + "reserved-words": "^0.1.2", "semver": "^5.5.0", "webpack": "^4.28.3", "webpack-cli": "^3.2.0" diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index bcb061a3..8769fc07 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -1,7 +1,6 @@ const traverse = require('@babel/traverse').default; const generate = require('@babel/generator').default; -let {writeFile} = require('./util'); let {Graph} = require('./graph'); function collectReferences(dep) { diff --git a/packages/wxa-cli/src/tree-shake/tansform-commonJS.js b/packages/wxa-cli/src/tree-shake/tansform-commonJS.js new file mode 100644 index 00000000..bf74b794 --- /dev/null +++ b/packages/wxa-cli/src/tree-shake/tansform-commonJS.js @@ -0,0 +1,454 @@ +const traverse = require('@babel/traverse').default; +const generate = require('@babel/generator').default; +let {check} = require('reserved-words'); +const {readFile, writeFile, parseESCode} = require('./util'); +let t = require('@babel/types'); +let path = require('path'); + +const state = { + globals: new Set(), + renamed: new Map(), + identifiers: new Set(), + isCJS: false, +}; + +const enter = (path) => { + let cursor = path; + + // Find the closest function scope or parent. + do { + // Ignore block statements. + if (t.isBlockStatement(cursor.scope.path)) { + continue; + } + + if (t.isFunction(cursor.scope.path) || t.isProgram(cursor.scope.path)) { + break; + } + } while ((cursor = cursor.scope.path.parentPath)); + + if (t.isProgram(cursor.scope.path)) { + const nodes = []; + const inner = []; + + // Break up the program, separate Nodes added by us from the nodes + // created by the user. + cursor.scope.path.node.body.filter((node) => { + // Keep replaced nodes together, these will not be wrapped. + if (node.__replaced) { + nodes.push(node); + } else { + inner.push(node); + } + }); + + const program = t.program([ + ...nodes, + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.functionExpression(null, [], t.blockStatement(inner)), + t.identifier('call') + ), + [t.identifier('module.exports')] + ) + ), + ]); + + cursor.scope.path.replaceWith(program); + state.isCJS = true; + } +}; + +function transform(ast, options = {}) { + traverse(ast, { + Program: { + exit(path) { + path.traverse({ + CallExpression: { + exit(path) { + const {node} = path; + + // Look for `require()` any renaming is assumed to be intentionally + // done to break state kind of check, so we won't look for aliases. + if ( + !options.exportsOnly && + t.isIdentifier(node.callee) && + node.callee.name === 'require' + ) { + // Require must be global for us to consider this a CommonJS + // module. + state.isCJS = true; + + // Check for nested string and template literals. + const isString = t.isStringLiteral( + node.arguments[0] + ); + const isLiteral = t.isTemplateLiteral( + node.arguments[0] + ); + + // Normalize the string value, default to the standard string + // literal format of `{ value: "" }`. + let str = null; + + if (isString) { + str = node.arguments[0]; + } else if (isLiteral) { + str = { + value: node.arguments[0].quasis[0].value + .raw, + }; + } else if (options.synchronousImport) { + const str = node.arguments[0]; + const newNode = t.expressionStatement( + t.callExpression(t.import(), [str]) + ); + + // @ts-ignore + newNode.__replaced = true; + + path.replaceWith(newNode); + + return; + } else { + throw new Error( + `Invalid require signature: ${path.toString()}` + ); + } + + const specifiers = []; + + // Convert to named import. + if ( + t.isObjectPattern(path.parentPath.node.id) + ) { + path.parentPath.node.id.properties.forEach( + (prop) => { + specifiers.push( + t.importSpecifier( + prop.value, + prop.key + ) + ); + + state.globals.add(prop.value.name); + } + ); + + const decl = t.importDeclaration( + specifiers, + t.stringLiteral(str.value) + ); + + // @ts-ignore + decl.__replaced = true; + + path.scope + .getProgramParent() + .path.unshiftContainer('body', decl); + path.parentPath.remove(); + } else if (str) { + // Convert to default import. + + const {parentPath} = path; + const {left} = parentPath.node; + // @ts-ignore + const oldId = !t.isMemberExpression(left) + ? left + : left.id; + + // Default to the closest likely identifier. + let id = oldId; + + // If we can't find an id, generate one from the import path. + if ( + !oldId || + !t.isProgram(parentPath.scope.path.type) + ) { + id = path.scope.generateUidIdentifier( + str.value + ); + } + + // Add state global name to the list. + state.globals.add(id.name); + + // Create an import declaration. + const decl = t.importDeclaration( + [t.importDefaultSpecifier(id)], + t.stringLiteral(str.value) + ); + + // @ts-ignore + decl.__replaced = true; + + // Push the declaration in the root scope. + path.scope + .getProgramParent() + .path.unshiftContainer('body', decl); + + // If we needed to generate or the change the id, then make an + // assignment so the values stay in sync. + if ( + oldId && + !t.isNodesEquivalent(oldId, id) + ) { + const newNode = t.expressionStatement( + t.assignmentExpression( + '=', + oldId, + id + ) + ); + + // @ts-ignore + newNode.__replaced = true; + + path.parentPath.parentPath.replaceWith( + newNode + ); + } else if (!oldId) { + // If we generated a new identifier for state, replace the inline + // call with the variable. + path.replaceWith(id); + } else { + // Otherwise completely remove. + + path.parentPath.remove(); + } + } + } + }, + }, + }); + + const programPath = path.scope.getProgramParent().path; + + // Even though we are pretty sure this isn't a CommonJS file, lets + // do one last sanity check for an `import` or `export` in the + // program path. + if (!state.isCJS) { + const lastImport = programPath + .get('body') + .filter((p) => p.isImportDeclaration()) + .pop(); + + const lastExport = programPath + .get('body') + .filter((p) => p.isExportDeclaration()) + .pop(); + + // Maybe it is a CJS file after-all. + if (!lastImport && !lastExport) { + state.isCJS = true; + } + } + + if (path.node.__replaced || !state.isCJS) { + return; + } + + const exportsAlias = t.variableDeclaration('var', [ + t.variableDeclarator( + t.identifier('exports'), + t.memberExpression( + t.identifier('module'), + t.identifier('exports') + ) + ), + ]); + + const moduleExportsAlias = t.variableDeclaration('var', [ + t.variableDeclarator( + t.identifier('module'), + t.objectExpression([ + t.objectProperty( + t.identifier('exports'), + t.objectExpression([]) + ), + ]) + ), + ]); + + // @ts-ignore + exportsAlias.__replaced = true; + // @ts-ignore + moduleExportsAlias.__replaced = true; + + // Add the `module` and `exports` globals into the program body, + // after the last `import` declaration. + const lastImport = programPath + .get('body') + .filter((p) => p.isImportDeclaration()) + .pop(); + + if (lastImport) { + lastImport.insertAfter(exportsAlias); + lastImport.insertAfter(moduleExportsAlias); + } else { + programPath.unshiftContainer('body', exportsAlias); + programPath.unshiftContainer('body', moduleExportsAlias); + } + + const defaultExport = t.exportDefaultDeclaration( + t.memberExpression( + t.identifier('module'), + t.identifier('exports') + ) + ); + + path.node.__replaced = true; + // @ts-ignore + defaultExport.__replaced = true; + + programPath.pushContainer('body', defaultExport); + }, + }, + ThisExpression: {enter}, + ReturnStatement: {enter}, + + ImportSpecifier: { + enter(path) { + const {name} = path.node.local; + + // If state import was renamed, ensure the source reflects it. + if (state.renamed.has(name)) { + const oldName = t.identifier(name); + const newName = t.identifier(state.renamed.get(name)); + + path.replaceWith(t.importSpecifier(newName, oldName)); + } + }, + }, + + AssignmentExpression: { + enter(path) { + if (path.node.__ignore) { + return; + } + + path.node.__ignore = true; + + // Check for module.exports. + if (t.isMemberExpression(path.node.left)) { + const moduleBinding = path.scope.getBinding('module'); + const exportsBinding = path.scope.getBinding('exports'); + + // Something like `module.exports.namedExport = true;`. + if ( + t.isMemberExpression(path.node.left.object) && + path.node.left.object.object.name === 'module' + ) { + if (!moduleBinding) { + state.isCJS = true; + return; + } + } else if ( + t.isIdentifier(path.node.left.object) && + path.node.left.object.name === 'module' + ) { + if (!moduleBinding) { + state.isCJS = true; + + // Looking at a re-exports, handled above. + if (t.isCallExpression(path.node.right)) { + return; + } + } + } else if (path.node.left.object.name === 'exports') { + // Check for regular exports + const {name} = path.node.left.property; + if ( + exportsBinding || + // If export is named "default" leave as is. + // It is not possible to export "default" as a named export. + // e.g. `export.default = 'a'` + name === 'default' + ) { + return; + } + + state.isCJS = true; + + let prop = path.node.right; + + if ( + (path.scope + .getProgramParent() + .hasBinding(prop.name) || + state.globals.has(prop.name)) && + // Don't rename `undefined`. + prop.name !== 'undefined' + ) { + prop = path.scope.generateUidIdentifier(prop.name); + + const oldName = path.node.right.name; + state.renamed.set(oldName, prop.name); + + // Add this new identifier into the globals and replace the + // right hand side with this replacement. + state.globals.add(prop.name); + path.get('right').replaceWith(prop); + path.scope.rename(oldName, prop.name); + } + + // If we set an invalid name, then abort out. + try { + // Ensure that the scope is clean before we inject new, + // potentially conflicting, variables. + const newName = + path.scope.generateUidIdentifier(name).name; + + path.scope.rename(name, newName); + + // Check if this name is reserved, if so, then bail out. + if (check(name)) { + return; + } + + const decl = t.exportNamedDeclaration( + t.variableDeclaration('let', [ + t.variableDeclarator( + path.node.left.property, + t.memberExpression( + t.identifier('exports'), + path.node.left.property + ) + ), + ]), + [] + ); + + if (!state.identifiers.has(name)) { + path.scope + .getProgramParent() + .path.pushContainer('body', decl); + state.identifiers.add(name); + } + } catch {} + } + } + }, + }, + }); +} + +let code = readFile(path.resolve(__dirname, './transform-test.js')); +let ast = parseESCode(code); + +transform(ast); + +const {code: outputCode} = generate( + ast, + { + /* options */ + decoratorsBeforeExport: true, + }, + code +); + +writeFile( + path.resolve(path.resolve(__dirname, './transform-test-a.js')), + outputCode +); diff --git a/packages/wxa-cli/src/tree-shake/transform-test-a.js b/packages/wxa-cli/src/tree-shake/transform-test-a.js new file mode 100644 index 00000000..f35bc664 --- /dev/null +++ b/packages/wxa-cli/src/tree-shake/transform-test-a.js @@ -0,0 +1,245 @@ +'use strict'; + +import _packageJson from "../package.json"; +import _crypto2 from "crypto"; +import _fsCache2 from "./fs-cache"; +import _mkdirp2 from "mkdirp"; +import _path2 from "path"; +import _fs2 from "fs"; +import _chalk2 from "chalk"; +import _babelRuntimeHelpersInteropRequireDefault from "@babel/runtime/helpers/interopRequireDefault"; +var module = { + exports: {} +}; +var exports = module.exports; +let _interopRequireDefault = _babelRuntimeHelpersInteropRequireDefault; +Object.defineProperty(exports, '__esModule', { + value: true +}); +exports.getFiles = _getFiles; // exports.getConfig = getConfig; + +exports.readFile = _readFile; +exports.writeFile = _writeFile; +exports.isFile = _isFile; +exports.isDir = _isDir; +exports.getRelative = _getRelative; +exports.getDistPath = _getDistPath; +exports.copy = _copy; +exports.amazingCache = _amazingCache; +exports.applyPlugins = _applyPlugins; +exports.isEmpty = _isEmpty; +exports.getHash = _getHash; +exports.getHashWithString = _getHashWithString; +exports.promiseSerial = _promiseSerial; +exports.getClassSet = _getClassSet; +exports.addClass = _addClass; +exports.removeClass = _removeClass; + +let _chalk = _interopRequireDefault(_chalk2); + +let _fs = _interopRequireDefault(_fs2); + +let _path = _interopRequireDefault(_path2); + +let _mkdirp = _interopRequireDefault(_mkdirp2); + +let _fsCache = _interopRequireDefault(_fsCache2); + +let _crypto = _interopRequireDefault(_crypto2); + +let current = process.cwd(); +let pkg = _packageJson; + +function _getFiles(dir = process.cwd(), prefix = '') { + dir = _path.default.normalize(dir); + let rst = []; + exports.ttt = 1; + + if (!_fs.default.existsSync(dir)) { + return rst; + } + + let files = _fs.default.readdirSync(dir); + + files.forEach(item => { + let filepath = dir + _path.default.sep + item; + + let stat = _fs.default.statSync(filepath); + + if (stat.isFile()) { + rst.push(prefix + item); + } else if (stat.isDirectory()) { + rst = rst.concat(_getFiles(filepath, _path.default.normalize(prefix + item + _path.default.sep))); + } + }); + return rst; +} // function getConfig() { +// let configPath = _path.default.join(process.cwd(), 'wxa.config.js'); +// let config = require(configPath); +// return config; +// } + + +function _readFile(p) { + let rst = ''; + p = typeof p === 'object' ? _path.default.join(p.dir, p.base) : p; + + try { + rst = _fs.default.readFileSync(p, 'utf-8'); + } catch (e) { + rst = null; + } + + return rst; +} + +function _writeFile(p, data) { + let opath = typeof p === 'string' ? _path.default.parse(p) : p; + + _mkdirp.default.sync(opath.dir); + + _fs.default.writeFileSync(p, data); +} + +function _isFile(p) { + p = typeof p === 'object' ? _path.default.join(p.dir, p.base) : p; + if (!_fs.default.existsSync(p)) return false; + return _fs.default.statSync(p).isFile(); +} + +function _isDir(p) { + // console.log(isDir, fs.existsSync(p), p); + if (!_fs.default.existsSync(p)) { + return false; + } + + return _fs.default.statSync(p).isDirectory(); +} + +function _getRelative(opath) { + return _path.default.relative(current, _path.default.join(opath.dir, opath.base)); +} + +function _getDistPath(opath, ext, src, dist) { + let relative; + opath = typeof opath === 'string' ? _path.default.parse(opath) : opath; + ext = ext ? ext[0] === '.' ? ext : '.' + ext : opath.ext; + + if (_path.default.relative(current, opath.dir).indexOf('node_modules') === 0) { + relative = _path.default.relative(_path.default.join(current, 'node_modules'), opath.dir); + relative = _path.default.join('npm', relative); + } else { + relative = _path.default.relative(_path.default.join(current, src), opath.dir); + } + + return _path.default.join(current, dist, relative, opath.name + ext); +} + +function _copy(from, to) { + return new Promise((resolve, reject) => { + _mkdirp.default.sync(_path.default.parse(to).dir); + + _fs.default.copyFile(from, to, err => { + if (err) return reject(err); + resolve(); + }); + }); +} + +function _amazingCache(params, needCache) { + let defaultOpts = { + directory: true, + identifier: JSON.stringify({ + '@wxa/cli2': pkg.version, + 'env': process.env.NODE_ENV || 'development' + }) + }; + let cacheParams = Object.assign({}, defaultOpts, params); + + if (needCache) { + return (0, _fsCache.default)(cacheParams); + } else { + let { + source, + transform, + options + } = cacheParams; + return transform(source, options); + } +} + +function _applyPlugins(plugins, compiler) { + if (plugins == null) return; // console.log(plugins); + + if (typeof plugins !== 'object') { + throw new Error('wxa配置文件有误,plugins'); + } + + if (!Array.isArray(plugins)) plugins = [plugins]; + plugins.forEach(plugin => plugin.apply(compiler)); +} + +function _isEmpty(n) { + return n == null || n === ''; +} + +function _getHash(filepath) { + let content = _readFile(filepath); + + return content == null ? Date.now() : _crypto.default.createHash('md5').update(content).digest('hex'); +} + +function _getHashWithString(content) { + return content == null ? Date.now() : _crypto.default.createHash('md5').update(content).digest('hex'); +} + +function _promiseSerial(funs) { + return funs.reduce((promise, fun) => { + return promise.then(result => fun().then(Array.prototype.concat.bind(result))); + }, Promise.resolve([])); +} + +function _getClassSet(classStr) { + let classList = []; + + if (classStr && typeof classStr === 'string') { + classList = classStr.split(' '); + } + + return new Set(classList); +} + +function _addClass(classStr, newClass) { + let classSet = _getClassSet(classStr); + + classSet.add(newClass); + return Array.from(classSet); +} + +function _removeClass(classStr, destClass) { + let classSet = _getClassSet(classStr); + + classSet.delete(destClass); + return Array.from(classSet); +} // # sourceMappingURL=utils.js.map + + +export let getFiles = exports.getFiles; +export let readFile = exports.readFile; +export let writeFile = exports.writeFile; +export let isFile = exports.isFile; +export let isDir = exports.isDir; +export let getRelative = exports.getRelative; +export let getDistPath = exports.getDistPath; +export let copy = exports.copy; +export let amazingCache = exports.amazingCache; +export let applyPlugins = exports.applyPlugins; +export let isEmpty = exports.isEmpty; +export let getHash = exports.getHash; +export let getHashWithString = exports.getHashWithString; +export let promiseSerial = exports.promiseSerial; +export let getClassSet = exports.getClassSet; +export let addClass = exports.addClass; +export let removeClass = exports.removeClass; +export let ttt = exports.ttt; +export default module.exports; \ No newline at end of file diff --git a/packages/wxa-cli/src/tree-shake/transform-test.js b/packages/wxa-cli/src/tree-shake/transform-test.js new file mode 100644 index 00000000..a386ef7a --- /dev/null +++ b/packages/wxa-cli/src/tree-shake/transform-test.js @@ -0,0 +1,233 @@ +'use strict'; + +let _interopRequireDefault = require('@babel/runtime/helpers/interopRequireDefault'); + +Object.defineProperty(exports, '__esModule', { + value: true, +}); +exports.getFiles = getFiles; +// exports.getConfig = getConfig; +exports.readFile = readFile; +exports.writeFile = writeFile; +exports.isFile = isFile; +exports.isDir = isDir; +exports.getRelative = getRelative; +exports.getDistPath = getDistPath; +exports.copy = copy; +exports.amazingCache = amazingCache; +exports.applyPlugins = applyPlugins; +exports.isEmpty = isEmpty; +exports.getHash = getHash; +exports.getHashWithString = getHashWithString; +exports.promiseSerial = promiseSerial; +exports.getClassSet = getClassSet; +exports.addClass = addClass; +exports.removeClass = removeClass; + +let _chalk = _interopRequireDefault(require('chalk')); + +let _fs = _interopRequireDefault(require('fs')); + +let _path = _interopRequireDefault(require('path')); + +let _mkdirp = _interopRequireDefault(require('mkdirp')); + +let _fsCache = _interopRequireDefault(require('./fs-cache')); + +let _crypto = _interopRequireDefault(require('crypto')); + +let current = process.cwd(); + +let pkg = require('../package.json'); + +function getFiles(dir = process.cwd(), prefix = '') { + dir = _path.default.normalize(dir); + let rst = []; + + exports.ttt= 1; + + if (!_fs.default.existsSync(dir)) { + return rst; + } + + let files = _fs.default.readdirSync(dir); + + files.forEach((item) => { + let filepath = dir + _path.default.sep + item; + + let stat = _fs.default.statSync(filepath); + + if (stat.isFile()) { + rst.push(prefix + item); + } else if (stat.isDirectory()) { + rst = rst.concat( + getFiles( + filepath, + _path.default.normalize(prefix + item + _path.default.sep) + ) + ); + } + }); + return rst; +} + +// function getConfig() { +// let configPath = _path.default.join(process.cwd(), 'wxa.config.js'); + +// let config = require(configPath); + +// return config; +// } + +function readFile(p) { + let rst = ''; + p = typeof p === 'object' ? _path.default.join(p.dir, p.base) : p; + + try { + rst = _fs.default.readFileSync(p, 'utf-8'); + } catch (e) { + rst = null; + } + + return rst; +} + +function writeFile(p, data) { + let opath = typeof p === 'string' ? _path.default.parse(p) : p; + + _mkdirp.default.sync(opath.dir); + + _fs.default.writeFileSync(p, data); +} + +function isFile(p) { + p = typeof p === 'object' ? _path.default.join(p.dir, p.base) : p; + if (!_fs.default.existsSync(p)) return false; + return _fs.default.statSync(p).isFile(); +} + +function isDir(p) { + // console.log(isDir, fs.existsSync(p), p); + if (!_fs.default.existsSync(p)) { + return false; + } + + return _fs.default.statSync(p).isDirectory(); +} + +function getRelative(opath) { + return _path.default.relative( + current, + _path.default.join(opath.dir, opath.base) + ); +} + +function getDistPath(opath, ext, src, dist) { + let relative; + opath = typeof opath === 'string' ? _path.default.parse(opath) : opath; + ext = ext ? (ext[0] === '.' ? ext : '.' + ext) : opath.ext; + + if ( + _path.default.relative(current, opath.dir).indexOf('node_modules') === 0 + ) { + relative = _path.default.relative( + _path.default.join(current, 'node_modules'), + opath.dir + ); + relative = _path.default.join('npm', relative); + } else { + relative = _path.default.relative( + _path.default.join(current, src), + opath.dir + ); + } + + return _path.default.join(current, dist, relative, opath.name + ext); +} + +function copy(from, to) { + return new Promise((resolve, reject) => { + _mkdirp.default.sync(_path.default.parse(to).dir); + + _fs.default.copyFile(from, to, (err) => { + if (err) return reject(err); + resolve(); + }); + }); +} + +function amazingCache(params, needCache) { + let defaultOpts = { + directory: true, + identifier: JSON.stringify({ + '@wxa/cli2': pkg.version, + 'env': process.env.NODE_ENV || 'development', + }), + }; + let cacheParams = Object.assign({}, defaultOpts, params); + + if (needCache) { + return (0, _fsCache.default)(cacheParams); + } else { + let {source, transform, options} = cacheParams; + return transform(source, options); + } +} + +function applyPlugins(plugins, compiler) { + if (plugins == null) return; // console.log(plugins); + + if (typeof plugins !== 'object') { +throw new Error('wxa配置文件有误,plugins'); +} + if (!Array.isArray(plugins)) plugins = [plugins]; + plugins.forEach((plugin) => plugin.apply(compiler)); +} + +function isEmpty(n) { + return n == null || n === ''; +} + +function getHash(filepath) { + let content = readFile(filepath); + return content == null + ? Date.now() + : _crypto.default.createHash('md5').update(content).digest('hex'); +} + +function getHashWithString(content) { + return content == null + ? Date.now() + : _crypto.default.createHash('md5').update(content).digest('hex'); +} + +function promiseSerial(funs) { + return funs.reduce((promise, fun) => { + return promise.then((result) => + fun().then(Array.prototype.concat.bind(result)) + ); + }, Promise.resolve([])); +} + +function getClassSet(classStr) { + let classList = []; + + if (classStr && typeof classStr === 'string') { + classList = classStr.split(' '); + } + + return new Set(classList); +} + +function addClass(classStr, newClass) { + let classSet = getClassSet(classStr); + classSet.add(newClass); + return Array.from(classSet); +} + +function removeClass(classStr, destClass) { + let classSet = getClassSet(classStr); + classSet.delete(destClass); + return Array.from(classSet); +} +// # sourceMappingURL=utils.js.map From 456f4e0f493cd9555ed75ff79091aedfd4070b78 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Fri, 18 Jun 2021 18:02:05 +0800 Subject: [PATCH 09/20] feat: commonjs shake --- packages/wxa-cli/example/cjs1.js | 144 +++ packages/wxa-cli/example/cjs2.js | 25 + packages/wxa-cli/example/index.js | 11 +- packages/wxa-cli/example/shaking/cjs1.js | 30 + packages/wxa-cli/example/shaking/cjs2.js | 0 packages/wxa-cli/example/shaking/index.js | 29 +- packages/wxa-cli/example/shaking/user.js | 2 +- packages/wxa-cli/package-lock.json | 1032 +++++++++++++++-- packages/wxa-cli/src/tree-shake/graph.js | 23 +- packages/wxa-cli/src/tree-shake/index.js | 85 +- .../src/tree-shake/tansform-commonJS.js | 915 ++++++++------- .../src/tree-shake/transform-test-a.js | 245 ---- .../wxa-cli/src/tree-shake/transform-test.js | 233 ---- 13 files changed, 1780 insertions(+), 994 deletions(-) create mode 100644 packages/wxa-cli/example/cjs1.js create mode 100644 packages/wxa-cli/example/cjs2.js create mode 100644 packages/wxa-cli/example/shaking/cjs1.js create mode 100644 packages/wxa-cli/example/shaking/cjs2.js delete mode 100644 packages/wxa-cli/src/tree-shake/transform-test-a.js delete mode 100644 packages/wxa-cli/src/tree-shake/transform-test.js diff --git a/packages/wxa-cli/example/cjs1.js b/packages/wxa-cli/example/cjs1.js new file mode 100644 index 00000000..b7ff0eec --- /dev/null +++ b/packages/wxa-cli/example/cjs1.js @@ -0,0 +1,144 @@ +let fn1= require('./cjs2').fn1; + + +fn1(); + + +Object.defineProperty(exports, '__esModule', { + value: true, +}); +exports.getFiles = getFiles; +// exports.getConfig = getConfig; +module.exports.readFile = readFile; +exports.writeFile = writeFile; +exports.isFile = isFile; +exports.isDir = isDir; +exports.getRelative = getRelative; +exports.getDistPath = getDistPath; +exports.copy = copy; +exports.amazingCache = amazingCache; +exports.applyPlugins = applyPlugins; +exports.isEmpty = isEmpty; +exports.getHash = getHash; +exports.getHashWithString = getHashWithString; +exports.promiseSerial = promiseSerial; +exports.getClassSet = getClassSet; +exports.addClass = addClass; +exports.removeClass = removeClass; + +module.exports ={getFiles}; + + +function getFiles(dir = process.cwd(), prefix = '') { + let rst = []; + + exports.rst= rst; + + let aaaa= 'aaa'; + // exports[aaaa] = aaaa; + + // let ttt= require('sss'); + + // console.log(ttt); + + // exports.addClass; + // module.exports.removeClass; + // exports[rst]; +} + +// function getConfig() { +// let configPath = _path.default.join(process.cwd(), 'wxa.config.js'); + +// let config = require(configPath); + +// return config; +// } + +function readFile(p) { + +} + +function writeFile(p, data) { + +} + +function isFile(p) { + +} + +function isDir(p) { + +} + +function getRelative(opath) { + +} + +function getDistPath(opath, ext, src, dist) { + +} + +function copy(from, to) { + +} + +function amazingCache(params, needCache) { + +} + +function applyPlugins(plugins, compiler) { + if (plugins == null) return; // console.log(plugins); + + if (typeof plugins !== 'object') { +throw new Error('wxa配置文件有误,plugins'); +} + if (!Array.isArray(plugins)) plugins = [plugins]; + plugins.forEach((plugin) => plugin.apply(compiler)); +} + +function isEmpty(n) { + return n == null || n === ''; +} + +function getHash(filepath) { +} + +function getHashWithString(content) { +} + +function promiseSerial(funs) { + return funs.reduce((promise, fun) => { + return promise.then((result) => + fun().then(Array.prototype.concat.bind(result)) + ); + }, Promise.resolve([])); +} + +function getClassSet(classStr) { + let classList = []; + + if (classStr && typeof classStr === 'string') { + classList = classStr.split(' '); + } + + return new Set(classList); +} + +function addClass(classStr, newClass) { + let classSet = getClassSet(classStr); + classSet.add(newClass); + return Array.from(classSet); +} + +function removeClass(classStr, destClass) { + let classSet = getClassSet(classStr); + classSet.delete(destClass); + return Array.from(classSet); +} +// # sourceMappingURL=utils.js.map + +exports.a=function m() { + +}; + + diff --git a/packages/wxa-cli/example/cjs2.js b/packages/wxa-cli/example/cjs2.js new file mode 100644 index 00000000..9fc85ea2 --- /dev/null +++ b/packages/wxa-cli/example/cjs2.js @@ -0,0 +1,25 @@ + + +function fn1(params) { + +} + + +function fn2(params) { + +} + + +function fn3(params) { + +} + + +exports.fn1 = fn1; +exports.fn2 = fn2; +exports.fn3 = fn3; + + +exports.fn4 = function fn4() { + +}; diff --git a/packages/wxa-cli/example/index.js b/packages/wxa-cli/example/index.js index a45ebb81..95802b95 100644 --- a/packages/wxa-cli/example/index.js +++ b/packages/wxa-cli/example/index.js @@ -1,6 +1,15 @@ /* eslint-disable one-var */ import getMyUser, {getName as getMyName} from './user'; import * as user from './user'; +import {getName as tttqw} from './user'; + +import {writeFile, isFile} from './cjs1'; + +writeFile(); +isFile(); + +getName(); + console.log(user); let a = {x: 1}, @@ -47,7 +56,6 @@ let obj = { (function(x, y) {})(); -getName(); // export default { // x: 1, // t() { @@ -55,7 +63,6 @@ getName(); // m, // age, // }; -export * from './user'; export function getName() {} // export {m as qqqqq, a as default}; diff --git a/packages/wxa-cli/example/shaking/cjs1.js b/packages/wxa-cli/example/shaking/cjs1.js new file mode 100644 index 00000000..8410bbe5 --- /dev/null +++ b/packages/wxa-cli/example/shaking/cjs1.js @@ -0,0 +1,30 @@ +let fn1 = require('./cjs2').fn1; + +fn1(); +Object.defineProperty(exports, '__esModule', { + value: true, +}); +exports.writeFile = writeFile; +exports.isFile = isFile; +module.exports = { + getFiles, +}; + +function getFiles(dir = process.cwd(), prefix = '') { + let rst = []; + exports.rst = rst; // exports[aaaa] = aaaa; + // let ttt= require('sss'); + // console.log(ttt); + // exports.addClass; + // module.exports.removeClass; + // exports[rst]; +} // function getConfig() { +// let configPath = _path.default.join(process.cwd(), 'wxa.config.js'); +// let config = require(configPath); +// return config; +// } + + +function writeFile(p, data) {} + +function isFile(p) {} diff --git a/packages/wxa-cli/example/shaking/cjs2.js b/packages/wxa-cli/example/shaking/cjs2.js new file mode 100644 index 00000000..e69de29b diff --git a/packages/wxa-cli/example/shaking/index.js b/packages/wxa-cli/example/shaking/index.js index e7adcf9b..69184d60 100644 --- a/packages/wxa-cli/example/shaking/index.js +++ b/packages/wxa-cli/example/shaking/index.js @@ -1,10 +1,14 @@ /* eslint-disable one-var */ import './user'; import * as user from './user'; +import {writeFile, isFile} from './cjs1'; +writeFile(); +isFile(); console.log(user); let a = { - x: 1 -}; + x: 1, +}, + n = 1; let t = 10; function m(x = 1, y) { @@ -15,16 +19,19 @@ function m(x = 1, y) { } m(); -[1, 2, 3].forEach(function (item) {}); +[1, 2, 3].forEach(function(item) {}); for (i = 0; i < 100; i++) {} +class Myclass { + [n] = 1; + [n] = () => {}; +} + export function mm() {} mm(); -(function (x, y) {})(); - -getName(); // export default { +(function(x, y) {})(); // export default { // x: 1, // t() { // }, @@ -32,11 +39,13 @@ getName(); // export default { // age, // }; + export function getName() {} // export {m as qqqqq, a as default}; // export {x, y} from './a'; -export {}; // eslint-disable-next-line no-var +export default function() {} +export {Myclass}; // eslint-disable-next-line no-var -export {}; -export {} from './user'; -export {} from './user'; \ No newline at end of file +export {mm as ttttttt}; +export {getName as tttt} from './user'; +export * as tttttt from './user'; diff --git a/packages/wxa-cli/example/shaking/user.js b/packages/wxa-cli/example/shaking/user.js index af191737..8c0a6fbd 100644 --- a/packages/wxa-cli/example/shaking/user.js +++ b/packages/wxa-cli/example/shaking/user.js @@ -3,4 +3,4 @@ export function getName() {} // export default function getUser(params) { // eslint-disable-next-line one-var export let mm1 = 1, - c = function mm2(params) {}; \ No newline at end of file + c = function mm2(params) {}; diff --git a/packages/wxa-cli/package-lock.json b/packages/wxa-cli/package-lock.json index 80d54fab..4a0b314e 100644 --- a/packages/wxa-cli/package-lock.json +++ b/packages/wxa-cli/package-lock.json @@ -237,7 +237,6 @@ "version": "7.11.6", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==", - "dev": true, "requires": { "@babel/code-frame": "^7.10.4", "@babel/generator": "^7.11.6", @@ -261,7 +260,6 @@ "version": "7.11.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", - "dev": true, "requires": { "@babel/code-frame": "^7.10.4", "@babel/generator": "^7.11.5", @@ -278,7 +276,6 @@ "version": "7.11.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", "lodash": "^4.17.19", @@ -289,7 +286,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, "requires": { "ms": "^2.1.1" } @@ -784,7 +780,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", - "dev": true, "requires": { "@babel/template": "^7.10.4", "@babel/traverse": "^7.10.4", @@ -795,7 +790,6 @@ "version": "7.11.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", - "dev": true, "requires": { "@babel/code-frame": "^7.10.4", "@babel/generator": "^7.11.5", @@ -812,7 +806,6 @@ "version": "7.11.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", "lodash": "^4.17.19", @@ -823,7 +816,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, "requires": { "ms": "^2.1.1" } @@ -1745,6 +1737,46 @@ "@xtuc/long": "4.2.2" } }, + "@wxa/compiler-babel": { + "version": "2.2.7", + "resolved": "https://registry.npm.taobao.org/@wxa/compiler-babel/download/@wxa/compiler-babel-2.2.7.tgz", + "integrity": "sha1-AydEuIAI8egJUNztqnDHmOEIXrA=", + "requires": { + "@babel/core": "^7.1.0", + "debug": "^4.0.1", + "find-cache-dir": "^2.0.0", + "mkdirp": "^0.5.1", + "zlib": "^1.0.5" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.3.1.tgz?cache=0&sync_timestamp=1607566533140&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.3.1.tgz", + "integrity": "sha1-8NIpxQXgxtjEmsVT0bE9wYP2su4=", + "requires": { + "ms": "2.1.2" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-2.1.0.tgz", + "integrity": "sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc=", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + } + } + }, + "@wxa/compiler-sass": { + "version": "2.2.7", + "resolved": "https://registry.nlark.com/@wxa/compiler-sass/download/@wxa/compiler-sass-2.2.7.tgz", + "integrity": "sha1-gGe1vzRPRFW0Yg95snOOqAePa1E=", + "requires": { + "node-sass": "^4.14.1" + } + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -1757,6 +1789,11 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npm.taobao.org/abbrev/download/abbrev-1.1.1.tgz", + "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=" + }, "acorn": { "version": "5.7.4", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", @@ -1784,7 +1821,6 @@ "version": "6.12.4", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", - "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1804,6 +1840,11 @@ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", "dev": true }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/amdefine/download/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", @@ -1812,8 +1853,7 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "3.2.1", @@ -1835,8 +1875,16 @@ "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npm.taobao.org/are-we-there-yet/download/are-we-there-yet-1.1.5.tgz", + "integrity": "sha1-SzXClE8GKov82mZBB2A1D+nd/CE=", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } }, "argparse": { "version": "1.0.10", @@ -1862,6 +1910,11 @@ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/array-find-index/download/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -1885,6 +1938,14 @@ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz", + "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", + "requires": { + "safer-buffer": "~2.1.0" + } + }, "asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -1932,6 +1993,11 @@ } } }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -1944,11 +2010,31 @@ "dev": true, "optional": true }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npm.taobao.org/async-foreach/download/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npm.taobao.org/aws4/download/aws4-1.11.0.tgz?cache=0&sync_timestamp=1604101166484&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faws4%2Fdownload%2Faws4-1.11.0.tgz", + "integrity": "sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk=" + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -2076,6 +2162,14 @@ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", "dev": true }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -2097,6 +2191,14 @@ "file-uri-to-path": "1.0.0" } }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npm.taobao.org/block-stream/download/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "~2.0.0" + } + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -2348,11 +2450,30 @@ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "dev": true }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-2.1.1.tgz?cache=0&sync_timestamp=1603923709404&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/camelcase-keys/download/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, "caniuse-lite": { "version": "1.0.30001125", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001125.tgz", "integrity": "sha512-9f+r7BW8Qli917mU3j0fUaTweT3f3vnX/Lcs+1C73V+RADmFme+Ih0Br8vONQi3X0lseOe6ZHfsZLCA8MSjxUA==" }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -2452,7 +2573,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, "requires": { "string-width": "^3.1.0", "strip-ansi": "^5.2.0", @@ -2462,20 +2582,17 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -2486,7 +2603,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -2499,6 +2615,11 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -2521,6 +2642,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.8.tgz", + "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -2559,6 +2688,11 @@ "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", "dev": true }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/console-control-strings/download/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, "constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", @@ -2569,7 +2703,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, "requires": { "safe-buffer": "~5.1.1" } @@ -2617,8 +2750,7 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "create-ecdh": { "version": "4.0.4", @@ -2665,6 +2797,15 @@ "sha.js": "^2.4.8" } }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -2684,12 +2825,28 @@ "randomfill": "^1.0.3" } }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npm.taobao.org/currently-unhandled/download/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "requires": { + "array-find-index": "^1.0.1" + } + }, "cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -2701,8 +2858,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decode-uri-component": { "version": "0.2.0", @@ -2765,6 +2921,16 @@ } } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, "des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -2882,6 +3048,15 @@ "stream-shift": "^1.0.0" } }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "electron-to-chromium": { "version": "1.3.564", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.564.tgz", @@ -2913,8 +3088,7 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "emojis-list": { "version": "3.0.0", @@ -2968,6 +3142,14 @@ "prr": "~1.0.1" } }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npm.taobao.org/error-ex/download/error-ex-1.3.2.tgz", + "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=", + "requires": { + "is-arrayish": "^0.2.1" + } + }, "es-abstract": { "version": "1.17.6", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", @@ -3312,6 +3494,11 @@ "homedir-polyfill": "^1.0.1" } }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz", + "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=" + }, "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", @@ -3400,11 +3587,15 @@ } } }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { "version": "2.2.7", @@ -3443,8 +3634,7 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-levenshtein": { "version": "2.0.6", @@ -3571,7 +3761,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -3626,6 +3815,21 @@ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz", + "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -3673,6 +3877,17 @@ "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", "optional": true }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npm.taobao.org/fstream/download/fstream-1.0.12.tgz", + "integrity": "sha1-Touo7i1Ivk99DeUFRVVI6uWTIEU=", + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -3684,23 +3899,57 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npm.taobao.org/gauge/download/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/gaze/download/gaze-1.1.3.tgz", + "integrity": "sha1-xEFzPhO5J6yMD/C0w7Az8ogSkko=", + "requires": { + "globule": "^1.0.0" + } + }, "gensync": { "version": "1.0.0-beta.1", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", - "dev": true + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.nlark.com/get-stdin/download/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -3788,17 +4037,40 @@ } } }, + "globule": { + "version": "1.3.2", + "resolved": "https://registry.npm.taobao.org/globule/download/globule-1.3.2.tgz", + "integrity": "sha1-2L3Z6eTu+PluJFmZpd7n612FKcQ=", + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" }, "growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npm.taobao.org/har-validator/download/har-validator-5.1.5.tgz", + "integrity": "sha1-HwgDufjLIMD6E4It8ezds2veHv0=", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -3811,7 +4083,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3826,6 +4097,11 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/has-unicode/download/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -3933,6 +4209,11 @@ "parse-passwd": "^1.0.0" } }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.8.9.tgz", + "integrity": "sha1-3/wL+aIcAiCQkPKqaUKeFBTa8/k=" + }, "htmlparser2": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", @@ -3958,6 +4239,16 @@ } } }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -4005,6 +4296,19 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "in-publish": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/in-publish/download/in-publish-2.0.1.tgz", + "integrity": "sha1-lIsaU1yAMFYc6lIvc/ePS+NX4Aw=" + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/indent-string/download/indent-string-2.1.0.tgz?cache=0&sync_timestamp=1618679442183&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Findent-string%2Fdownload%2Findent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "^2.0.0" + } + }, "infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", @@ -4128,6 +4432,11 @@ } } }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -4196,6 +4505,19 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.nlark.com/is-finite/download/is-finite-1.1.0.tgz", + "integrity": "sha1-kEE1x3+0LAZB1qobzbxNqo2ggvM=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz?cache=0&sync_timestamp=1618552489864&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-fullwidth-code-point%2Fdownload%2Fis-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -4239,6 +4561,16 @@ "has-symbols": "^1.0.1" } }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npm.taobao.org/is-utf8/download/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -4264,6 +4596,11 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, "js-base64": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", @@ -4284,6 +4621,11 @@ "esprima": "^4.0.0" } }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -4295,11 +4637,15 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz?cache=0&sync_timestamp=1609553637722&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-schema%2Fdownload%2Fjson-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -4307,6 +4653,11 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, "json5": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", @@ -4315,6 +4666,17 @@ "minimist": "^1.2.5" } }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -4343,6 +4705,25 @@ "type-check": "~0.3.2" } }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -4375,7 +4756,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -4394,11 +4774,19 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npm.taobao.org/loud-rejection/download/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -4408,7 +4796,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, "requires": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -4419,6 +4806,11 @@ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/map-obj/download/map-obj-1.0.1.tgz?cache=0&sync_timestamp=1617771232226&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmap-obj%2Fdownload%2Fmap-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -4448,6 +4840,23 @@ "readable-stream": "^2.0.1" } }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.nlark.com/meow/download/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4568,6 +4977,19 @@ } } }, + "mime-db": { + "version": "1.48.0", + "resolved": "https://registry.nlark.com/mime-db/download/mime-db-1.48.0.tgz?cache=0&sync_timestamp=1622433567590&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmime-db%2Fdownload%2Fmime-db-1.48.0.tgz", + "integrity": "sha1-41sxBF3X6to6qtU37YijOvvvLR0=" + }, + "mime-types": { + "version": "2.1.31", + "resolved": "https://registry.nlark.com/mime-types/download/mime-types-2.1.31.tgz", + "integrity": "sha1-oA12t0MXxh+cLbIhi46fjpxcnms=", + "requires": { + "mime-db": "1.48.0" + } + }, "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", @@ -4678,9 +5100,7 @@ "nan": { "version": "2.14.1", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true, - "optional": true + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" }, "nanomatch": { "version": "1.2.13", @@ -4718,6 +5138,32 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.nlark.com/node-gyp/download/node-gyp-3.8.0.tgz", + "integrity": "sha1-VAMEJhwzDoDQ1e3OJTpoyzlkIYw=", + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + } + } + }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -4774,16 +5220,103 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==" }, + "node-sass": { + "version": "4.14.1", + "resolved": "https://registry.nlark.com/node-sass/download/node-sass-4.14.1.tgz", + "integrity": "sha1-mch+wu+3BH7WOPtMnbfzpC4iF7U=", + "requires": { + "async-foreach": "^0.1.3", + "chalk": "^1.1.1", + "cross-spawn": "^3.0.0", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "in-publish": "^2.0.0", + "lodash": "^4.17.15", + "meow": "^3.7.0", + "mkdirp": "^0.5.1", + "nan": "^2.13.2", + "node-gyp": "^3.8.0", + "npmlog": "^4.0.0", + "request": "^2.88.0", + "sass-graph": "2.2.5", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.nlark.com/chalk/download/chalk-1.1.3.tgz?cache=0&sync_timestamp=1618995367379&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.nlark.com/supports-color/download/supports-color-2.0.0.tgz?cache=0&sync_timestamp=1622293670728&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npm.taobao.org/nopt/download/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npm.taobao.org/normalize-package-data/download/normalize-package-data-2.5.0.tgz", + "integrity": "sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg=", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npm.taobao.org/npmlog/download/npmlog-4.1.2.tgz", + "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.nlark.com/number-is-nan/download/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz", + "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-copy": { "version": "0.1.0", @@ -4886,16 +5419,29 @@ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npm.taobao.org/os-homedir/download/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npm.taobao.org/osenv/download/osenv-0.1.5.tgz", + "integrity": "sha1-hc36+uso6Gd/QW4odZK18/SepBA=", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -4904,7 +5450,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -4912,8 +5457,7 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "pako": { "version": "1.0.11", @@ -4945,6 +5489,14 @@ "safe-buffer": "^5.1.1" } }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz?cache=0&sync_timestamp=1610966709037&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse-json%2Fdownload%2Fparse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -4994,6 +5546,23 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/path-type/download/path-type-1.1.0.tgz?cache=0&sync_timestamp=1611752058913&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-type%2Fdownload%2Fpath-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, "pbkdf2": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", @@ -5007,6 +5576,11 @@ "sha.js": "^2.4.8" } }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -5015,14 +5589,25 @@ "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npm.taobao.org/pinkie-promise/download/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, "requires": { "find-up": "^3.0.0" } @@ -5086,8 +5671,7 @@ "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "progress": { "version": "2.0.3", @@ -5120,8 +5704,12 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npm.taobao.org/psl/download/psl-1.8.0.tgz", + "integrity": "sha1-kyb4vPsBOtzABf3/BWrM4CDlHCQ=" }, "public-encrypt": { "version": "4.0.3", @@ -5181,8 +5769,12 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz?cache=0&sync_timestamp=1616385315895&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fqs%2Fdownload%2Fqs-6.5.2.tgz", + "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=" }, "querystring": { "version": "0.2.0", @@ -5215,11 +5807,48 @@ "safe-buffer": "^5.1.0" } }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npm.taobao.org/read-pkg/download/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-1.0.1.tgz?cache=0&sync_timestamp=1616916344510&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fread-pkg-up%2Fdownload%2Fread-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-1.1.2.tgz?cache=0&sync_timestamp=1599054261724&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-up%2Fdownload%2Ffind-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/path-exists/download/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5246,6 +5875,15 @@ "resolve": "^1.1.6" } }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.nlark.com/redent/download/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, "regenerate": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", @@ -5337,17 +5975,50 @@ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.nlark.com/repeating/download/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npm.taobao.org/request/download/request-2.88.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frequest%2Fdownload%2Frequest-2.88.2.tgz", + "integrity": "sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM=", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "require-uncached": { "version": "1.0.3", @@ -5442,7 +6113,6 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -5512,6 +6182,17 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "sass-graph": { + "version": "2.2.5", + "resolved": "https://registry.npm.taobao.org/sass-graph/download/sass-graph-2.2.5.tgz", + "integrity": "sha1-qYHIdEa4MZ2W3OBnHkh4eb0kwug=", + "requires": { + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^13.3.2" + } + }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -5531,6 +6212,25 @@ } } }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npm.taobao.org/scss-tokenizer/download/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "requires": { + "js-base64": "^2.1.8", + "source-map": "^0.4.2" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -5548,8 +6248,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-value": { "version": "2.0.1", @@ -5801,6 +6500,34 @@ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.1.1.tgz", + "integrity": "sha1-3s6BrJweZxPl99G28X1Gj6U9iak=", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npm.taobao.org/spdx-exceptions/download/spdx-exceptions-2.3.0.tgz", + "integrity": "sha1-PyjOGnegA3JoPq3kpDMYNSeiFj0=" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npm.taobao.org/spdx-expression-parse/download/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha1-z3D1BILu/cmOPOCmgz5KU87rpnk=", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.9", + "resolved": "https://registry.nlark.com/spdx-license-ids/download/spdx-license-ids-3.0.9.tgz?cache=0&sync_timestamp=1621652583280&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fspdx-license-ids%2Fdownload%2Fspdx-license-ids-3.0.9.tgz", + "integrity": "sha1-illRNd75WSvaaXCUdPHL7qfCRn8=" + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -5815,6 +6542,22 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz", + "integrity": "sha1-+2YcC+8ps520B2nuOfpwCT1vaHc=", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", @@ -5843,6 +6586,14 @@ } } }, + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npm.taobao.org/stdout-stream/download/stdout-stream-1.4.1.tgz", + "integrity": "sha1-WsF0zdXNcmEEqgwLK9g4FdjVNd4=", + "requires": { + "readable-stream": "^2.0.1" + } + }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -5882,6 +6633,16 @@ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.nlark.com/string-width/download/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, "string.prototype.trimend": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", @@ -5912,11 +6673,26 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "^2.0.0" } }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.nlark.com/strip-bom/download/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.nlark.com/strip-indent/download/strip-indent-1.0.1.tgz?cache=0&sync_timestamp=1620053310624&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fstrip-indent%2Fdownload%2Fstrip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "requires": { + "get-stdin": "^4.0.1" + } + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -6007,6 +6783,16 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npm.taobao.org/tar/download/tar-2.2.2.tgz", + "integrity": "sha1-DKiEhWLHKZuLRG/2pNYM27I+3EA=", + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, "terser": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", @@ -6148,6 +6934,28 @@ "is-number": "^7.0.0" } }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.5.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftough-cookie%2Fdownload%2Ftough-cookie-2.5.0.tgz", + "integrity": "sha1-zZ+yoKodWhK0c72fuW+j3P9lreI=", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.nlark.com/trim-newlines/download/trim-newlines-1.0.0.tgz?cache=0&sync_timestamp=1623341510447&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftrim-newlines%2Fdownload%2Ftrim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npm.taobao.org/true-case-path/download/true-case-path-1.0.3.tgz", + "integrity": "sha1-+BO1qMhrQNpZYGcisUTjIleZ9H0=", + "requires": { + "glob": "^7.1.2" + } + }, "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", @@ -6159,6 +6967,19 @@ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -6274,7 +7095,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", - "dev": true, "requires": { "punycode": "^2.1.0" } @@ -6329,6 +7149,11 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.nlark.com/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1622213136953&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz", + "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=" + }, "v8-compile-cache": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", @@ -6340,6 +7165,25 @@ "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=" }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -6677,8 +7521,15 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npm.taobao.org/wide-align/download/wide-align-1.1.3.tgz", + "integrity": "sha1-rgdOa9wMFKQx6ATmJFScYzsABFc=", + "requires": { + "string-width": "^1.0.2 || 2" + } }, "word-wrap": { "version": "1.2.3", @@ -6699,7 +7550,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, "requires": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", @@ -6709,20 +7559,17 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -6733,7 +7580,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -6763,20 +7609,17 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { "version": "13.3.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, "requires": { "cliui": "^5.0.0", "find-up": "^3.0.0", @@ -6793,20 +7636,17 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -6817,7 +7657,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -6828,7 +7667,6 @@ "version": "13.1.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -6837,10 +7675,14 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" } } + }, + "zlib": { + "version": "1.0.5", + "resolved": "https://registry.npm.taobao.org/zlib/download/zlib-1.0.5.tgz", + "integrity": "sha1-bnyXL8NxxkWmr7A6sUdp3vEU/MA=" } } } diff --git a/packages/wxa-cli/src/tree-shake/graph.js b/packages/wxa-cli/src/tree-shake/graph.js index 9296547a..d5b57acf 100644 --- a/packages/wxa-cli/src/tree-shake/graph.js +++ b/packages/wxa-cli/src/tree-shake/graph.js @@ -1,6 +1,7 @@ const traverse = require('@babel/traverse').default; const {Scope} = require('./scope'); const {readFile, resolveDepSrc, parseESCode} = require('./util'); +let {TransformCommonJs} = require('./tansform-commonJS'); class Graph { constructor(entries) { @@ -43,6 +44,7 @@ class Graph { let identifierNode = node[attr]; // 类似于export default function(){} + // 这类声明也不能在本文件内使用,直接忽略 if (!identifierNode || !identifierNode.name) { return; } @@ -97,6 +99,9 @@ class Graph { // import 的声明 case 'ImportDeclaration': node.specifiers.forEach((specifier) => { + if (node.$t_cjs_temp_import) { + return; + } addToScope(specifier, 'local', true); }); break; @@ -186,7 +191,7 @@ class Graph { } else { exportInfo.default = node; } - + markShakingFlag(exportInfo.default); break; case 'ExportAllDeclaration': @@ -221,11 +226,15 @@ class Graph { return analyzedFile[src]; } + // console.log(src); + let imports = {}; let exports = {}; let code = content || readFile(src); let ast = parseESCode(code); + let transformCommonJs = new TransformCommonJs({src, code, ast}); + let scope = new Scope(); traverse(ast, { @@ -304,6 +313,17 @@ class Graph { * } */ + transformCommonJs.state.childScopeRequires.forEach( + (names, requireSrc) => { + let abSrc = this.getAbsolutePath(src, requireSrc); + let info = Array.from(names).map((name) => ({ + name: 'child_scope_require', + })); + imports[abSrc] = imports[abSrc] || {}; + imports[abSrc] = {...imports[abSrc], ...info}; + } + ); + let dep = { src, code, @@ -313,6 +333,7 @@ class Graph { children: [], scope, isRoot, + transformCommonJs, }; analyzedFile[src] = dep; diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index 8769fc07..8c676a7b 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -1,5 +1,6 @@ const traverse = require('@babel/traverse').default; const generate = require('@babel/generator').default; +const {writeFile} = require('./util'); let {Graph} = require('./graph'); @@ -65,6 +66,7 @@ function collectReferences(dep) { dep.children.forEach((child) => collectReferences(child)); } +const REQUIRE_TO_IMPORT_DEFAULT = 'require_to_import_default'; /** * export node 有一个_shake标志,如果该export没有被import,或者被import后没有使用,_shake = 1 * 在这里,遍历全局文件树,根据import和export关系,对没使用的export进行标记 @@ -103,10 +105,15 @@ function shake(dep) { } }; - let hasAll = usedNames.some((name) => name === '*'); + let hasAll = usedNames.some( + (name) => name === '*' || name === REQUIRE_TO_IMPORT_DEFAULT + ); if (hasAll) { - let hasDefalut = usedNames.some((name) => name === 'default'); + let hasDefalut = usedNames.some( + (name) => + name === 'default' || name === REQUIRE_TO_IMPORT_DEFAULT + ); let markedDefalut = false; if (localExports) { Object.entries(localExports[1]).forEach(([name, node]) => { @@ -139,6 +146,17 @@ function shake(dep) { } else { usedNames.forEach((name) => { if (localExports) { + // if (name === REQUIRE_TO_IMPORT_DEFAULT) { + // Object.values(localExports[1]).forEach((node) => { + // // exports 转换的 export 节点 + // if (node.$t_cjs_temp_export) { + // node._shake = 0; + // } + // }); + + // return; + // } + let node = localExports[1][name]; if (node) { node._shake = 0; @@ -158,10 +176,6 @@ function shake(dep) { }); } - if (childSrc.endsWith('store\\configure.js')) { - console.log('1111'); - } - Object.entries(usedExports).forEach((src, value) => { mark(child, Object.keys(value), src); }); @@ -172,6 +186,23 @@ function shake(dep) { let usedNames = []; Object.entries(value).forEach(([name, node]) => { + // require 转成的 import default 节点 + // 这些节点默认被本文件使用 + if (node.$t_cjs_temp_default_import) { + usedNames.push(REQUIRE_TO_IMPORT_DEFAULT); + return; + } + + if (node === 'child_scope_require') { + if (name === 'default') { + usedNames.push(REQUIRE_TO_IMPORT_DEFAULT); + } else { + usedNames.push(name); + } + + return; + } + if (node._usedByNodes && node._usedByNodes.length) { usedNames.push(name); } @@ -228,6 +259,9 @@ function remove(dep) { }); }; + let transformCommonJs = dep.transformCommonJs; + transformCommonJs.traverseTransformedModuleDeclaration(markRemoved); + /** * 遍历exports,shake 标志表示该节点是否被外部有效的 import(即import的方法变量被使用过) * 如果shake=1,表示没有被有效import过 @@ -239,6 +273,22 @@ function remove(dep) { */ Object.entries(exports).forEach(([src, value]) => { Object.entries(value).forEach(([name, node]) => { + if (node.$t_cjs_temp_export) { + if ( + !transformCommonJs.state.isDynamicUsedExportsProperty && + node._shake === 1 && + !transformCommonJs.state.usedExports.has(name) + ) { + let cjsExportNode = transformCommonJs.getCJSExport(node); + if (cjsExportNode) { + console.log('111'); + markRemoved(cjsExportNode); + } + } + + return; + } + if ( node._shake === 1 && (!node._usedByNodes || @@ -269,9 +319,15 @@ function output(dep) { return; } + console.log(src); + if (src.endsWith('cjs1.js')) { + console.log('ss'); + } + traverse(ast, { enter(path) { let {node} = path; + // console.log(path.toString()); if (node._removed === 1) { path.remove(); } @@ -287,10 +343,10 @@ function output(dep) { code ); - // writeFile( - // path.resolve(path.dirname(src), './shaking', path.basename(src)), - // outputCode - // ); + writeFile( + path.resolve(path.dirname(src), './shaking', path.basename(src)), + outputCode + ); contents[src] = outputCode; @@ -334,10 +390,11 @@ module.exports = { start, }; -// console.time('end'); -// let entrySrc = path.resolve(__dirname, '../../example/index.js'); -// start([entrySrc]); -// console.timeEnd('end'); +console.time('end'); +let path = require('path'); +let entrySrc = path.resolve(__dirname, '../../example/index.js'); +start([{src: entrySrc}]); +console.timeEnd('end'); // function name(params) { // console.log(m); diff --git a/packages/wxa-cli/src/tree-shake/tansform-commonJS.js b/packages/wxa-cli/src/tree-shake/tansform-commonJS.js index bf74b794..056807af 100644 --- a/packages/wxa-cli/src/tree-shake/tansform-commonJS.js +++ b/packages/wxa-cli/src/tree-shake/tansform-commonJS.js @@ -5,450 +5,579 @@ const {readFile, writeFile, parseESCode} = require('./util'); let t = require('@babel/types'); let path = require('path'); -const state = { - globals: new Set(), - renamed: new Map(), - identifiers: new Set(), - isCJS: false, -}; +let options = {}; + +function getStaticValue(node) { + if (t.isStringLiteral(node) || t.isNumericLiteral(node)) { + return node.value; + } else if ( + t.isTemplateLiteral(node) && + !node.arguments[0].expressions.length + ) { + return node.arguments[0].quasis[0].value.raw; + } -const enter = (path) => { - let cursor = path; + return false; +} - // Find the closest function scope or parent. - do { - // Ignore block statements. - if (t.isBlockStatement(cursor.scope.path)) { - continue; - } +function getStaticMemberProValue(node) { + if (node.computed) { + return getStaticValue(node.property); + } - if (t.isFunction(cursor.scope.path) || t.isProgram(cursor.scope.path)) { - break; + return node.property.name; +} + +class TransformCommonJs { + state = { + globalESMImports: new Map(), + globalESMExports: new Map(), + renamed: new Map(), + identifiers: new Set(), + isCJS: false, + isESM: false, + childScopeRequires: new Map(), + deletedNodes: new Map(), + usedExports: new Set(), + isDynamicUsedExportsProperty: false, + }; + + constructor({src, code, ast}) { + this.src = src; + this.code = code; + this.ast = ast || parseESCode(code); + + let dynamicRequireTargets = options.dynamicRequireTargets || []; + // 如果一个模块被其他模块动态导入 + // 不对这个模块做任何处理 + if (dynamicRequireTargets.includes(src)) { + return {src, code}; } - } while ((cursor = cursor.scope.path.parentPath)); - - if (t.isProgram(cursor.scope.path)) { - const nodes = []; - const inner = []; - - // Break up the program, separate Nodes added by us from the nodes - // created by the user. - cursor.scope.path.node.body.filter((node) => { - // Keep replaced nodes together, these will not be wrapped. - if (node.__replaced) { - nodes.push(node); - } else { - inner.push(node); - } - }); - const program = t.program([ - ...nodes, - t.expressionStatement( - t.callExpression( - t.memberExpression( - t.functionExpression(null, [], t.blockStatement(inner)), - t.identifier('call') - ), - [t.identifier('module.exports')] - ) - ), - ]); - - cursor.scope.path.replaceWith(program); - state.isCJS = true; - } -}; + this.transform(this.ast, options); -function transform(ast, options = {}) { - traverse(ast, { - Program: { - exit(path) { - path.traverse({ - CallExpression: { - exit(path) { - const {node} = path; - - // Look for `require()` any renaming is assumed to be intentionally - // done to break state kind of check, so we won't look for aliases. - if ( - !options.exportsOnly && - t.isIdentifier(node.callee) && - node.callee.name === 'require' - ) { - // Require must be global for us to consider this a CommonJS - // module. - state.isCJS = true; + console.log('childScopeRequires', this.state.childScopeRequires); + console.log('usedExports', this.state.usedExports); + console.log( + 'isDynamicUsedExportsProperty', + this.state.isDynamicUsedExportsProperty + ); - // Check for nested string and template literals. - const isString = t.isStringLiteral( - node.arguments[0] - ); - const isLiteral = t.isTemplateLiteral( - node.arguments[0] - ); + // this.deleteTransformedModuleDeclaration(); + } - // Normalize the string value, default to the standard string - // literal format of `{ value: "" }`. - let str = null; + reset() { + this.state.deletedNodes.forEach((path, node) => { + if (t.isProgram(path)) { + path.node.body.push(node); + } else { + path.insertBefore(node); + } + }); + } - if (isString) { - str = node.arguments[0]; - } else if (isLiteral) { - str = { - value: node.arguments[0].quasis[0].value - .raw, - }; - } else if (options.synchronousImport) { - const str = node.arguments[0]; - const newNode = t.expressionStatement( - t.callExpression(t.import(), [str]) - ); + deleteTransformedModuleDeclaration() { + this.state.globalESMImports.forEach((paths, importPath) => { + importPath.remove(); + }); - // @ts-ignore - newNode.__replaced = true; + this.state.globalESMExports.forEach((paths, exportPath) => { + exportPath.remove(); + }); + } - path.replaceWith(newNode); + traverseTransformedModuleDeclaration(cb) { + this.state.globalESMImports.forEach((paths, importPath) => { + cb(importPath.node); + }); - return; - } else { - throw new Error( - `Invalid require signature: ${path.toString()}` - ); - } + this.state.globalESMExports.forEach((paths, exportPath) => { + cb(exportPath.node); + }); + } - const specifiers = []; - - // Convert to named import. - if ( - t.isObjectPattern(path.parentPath.node.id) - ) { - path.parentPath.node.id.properties.forEach( - (prop) => { - specifiers.push( - t.importSpecifier( - prop.value, - prop.key - ) - ); - - state.globals.add(prop.value.name); - } - ); - - const decl = t.importDeclaration( - specifiers, - t.stringLiteral(str.value) - ); - - // @ts-ignore - decl.__replaced = true; - - path.scope - .getProgramParent() - .path.unshiftContainer('body', decl); - path.parentPath.remove(); - } else if (str) { - // Convert to default import. - - const {parentPath} = path; - const {left} = parentPath.node; - // @ts-ignore - const oldId = !t.isMemberExpression(left) - ? left - : left.id; - - // Default to the closest likely identifier. - let id = oldId; - - // If we can't find an id, generate one from the import path. - if ( - !oldId || - !t.isProgram(parentPath.scope.path.type) - ) { - id = path.scope.generateUidIdentifier( - str.value - ); - } - - // Add state global name to the list. - state.globals.add(id.name); - - // Create an import declaration. - const decl = t.importDeclaration( - [t.importDefaultSpecifier(id)], - t.stringLiteral(str.value) - ); - - // @ts-ignore - decl.__replaced = true; - - // Push the declaration in the root scope. - path.scope - .getProgramParent() - .path.unshiftContainer('body', decl); - - // If we needed to generate or the change the id, then make an - // assignment so the values stay in sync. - if ( - oldId && - !t.isNodesEquivalent(oldId, id) - ) { - const newNode = t.expressionStatement( - t.assignmentExpression( - '=', - oldId, - id - ) - ); - - // @ts-ignore - newNode.__replaced = true; - - path.parentPath.parentPath.replaceWith( - newNode - ); - } else if (!oldId) { - // If we generated a new identifier for state, replace the inline - // call with the variable. - path.replaceWith(id); - } else { - // Otherwise completely remove. - - path.parentPath.remove(); - } - } - } - }, - }, - }); - - const programPath = path.scope.getProgramParent().path; - - // Even though we are pretty sure this isn't a CommonJS file, lets - // do one last sanity check for an `import` or `export` in the - // program path. - if (!state.isCJS) { - const lastImport = programPath - .get('body') - .filter((p) => p.isImportDeclaration()) - .pop(); - - const lastExport = programPath - .get('body') - .filter((p) => p.isExportDeclaration()) - .pop(); - - // Maybe it is a CJS file after-all. - if (!lastImport && !lastExport) { - state.isCJS = true; - } + deleteCJSExport(esmExportNode) { + Array.from(this.state.globalESMExports).some( + ([exportPath, cjsPaths]) => { + if (this.isChildNode(exportPath.node, esmExportNode)) { + cjsPaths.forEach((p) => p.remove()); + return true; } + } + ); + } - if (path.node.__replaced || !state.isCJS) { - return; - } + getCJSExport(esmExportNode) { + let node = null; - const exportsAlias = t.variableDeclaration('var', [ - t.variableDeclarator( - t.identifier('exports'), - t.memberExpression( - t.identifier('module'), - t.identifier('exports') - ) - ), - ]); - - const moduleExportsAlias = t.variableDeclaration('var', [ - t.variableDeclarator( - t.identifier('module'), - t.objectExpression([ - t.objectProperty( - t.identifier('exports'), - t.objectExpression([]) - ), - ]) - ), - ]); - - // @ts-ignore - exportsAlias.__replaced = true; - // @ts-ignore - moduleExportsAlias.__replaced = true; - - // Add the `module` and `exports` globals into the program body, - // after the last `import` declaration. - const lastImport = programPath - .get('body') - .filter((p) => p.isImportDeclaration()) - .pop(); - - if (lastImport) { - lastImport.insertAfter(exportsAlias); - lastImport.insertAfter(moduleExportsAlias); - } else { - programPath.unshiftContainer('body', exportsAlias); - programPath.unshiftContainer('body', moduleExportsAlias); + Array.from(this.state.globalESMExports).some( + ([exportPath, cjsPaths]) => { + if (this.isChildNode(exportPath.node, esmExportNode)) { + node = cjsPaths[0].node; + return true; } + } + ); - const defaultExport = t.exportDefaultDeclaration( - t.memberExpression( - t.identifier('module'), - t.identifier('exports') - ) - ); - - path.node.__replaced = true; - // @ts-ignore - defaultExport.__replaced = true; - - programPath.pushContainer('body', defaultExport); - }, - }, - ThisExpression: {enter}, - ReturnStatement: {enter}, + return node; + } - ImportSpecifier: { + markNodeDeep(node, flag) { + node[flag] = true; + traverse(node, { + noScope: true, enter(path) { - const {name} = path.node.local; + let {node} = path; + node[flag] = true; + }, + }); + } - // If state import was renamed, ensure the source reflects it. - if (state.renamed.has(name)) { - const oldName = t.identifier(name); - const newName = t.identifier(state.renamed.get(name)); + isChildNode(parent, child) { + if (parent === child) { + return true; + } - path.replaceWith(t.importSpecifier(newName, oldName)); - } - }, - }, + let is = false; - AssignmentExpression: { + traverse(parent, { + noScope: true, enter(path) { - if (path.node.__ignore) { - return; + let {node} = path; + if (node === child) { + is = true; + path.stop(); } + }, + }); - path.node.__ignore = true; - - // Check for module.exports. - if (t.isMemberExpression(path.node.left)) { - const moduleBinding = path.scope.getBinding('module'); - const exportsBinding = path.scope.getBinding('exports'); + return is; + } - // Something like `module.exports.namedExport = true;`. + transform(ast, options = {}) { + traverse(ast, { + Program: { + exit: (path) => { + // let allDeletePaths = []; + + // this.state.globalESMImports.forEach((paths) => { + // allDeletePaths = allDeletePaths.concat(paths); + // }); + + // this.state.globalESMExports.forEach((paths) => { + // allDeletePaths = allDeletePaths.concat(paths); + // }); + + // allDeletePaths.forEach((path) => { + // let allNextSiblingPaths = path.getAllNextSiblings(); + + // if (!allNextSiblingPaths.length) { + // this.state.deletedNodes.set( + // path.node, + // path.parentPath + // ); + // path.remove(); + // return; + // } + + // for (let i = 0; i < allNextSiblingPaths.length; i++) { + // let nextPath = allNextSiblingPaths[i]; + // let last = i === allNextSiblingPaths.length - 1; + // let find = + // !allDeletePaths.includes(nextPath) || last; + + // if (last) { + // nextPath = path.parentPath; + // } + + // if (find) { + // this.state.deletedNodes.set( + // path.node, + // nextPath + // ); + // path.remove(); + // break; + // } + // } + // }); + + let globalESMImports = new Map(); + this.state.globalESMImports.forEach((paths, node) => { + this.markNodeDeep(node, '$t_cjs_temp_import'); + let importPath = path.unshiftContainer('body', node)[0]; + globalESMImports.set(importPath, paths); + }); + this.state.globalESMImports = globalESMImports; + + let globalESMExports = new Map(); + this.state.globalESMExports.forEach((paths, node) => { + this.markNodeDeep(node, '$t_cjs_temp_export'); + let exportPath = path.pushContainer('body', node)[0]; + globalESMExports.set(exportPath, paths); + }); + this.state.globalESMExports = globalESMExports; + }, + }, + CallExpression: { + enter: (path) => { + const {node} = path; + // Look for `require()` any renaming is assumed to be intentionally + // done to break state kind of check, so we won't look for aliases. if ( - t.isMemberExpression(path.node.left.object) && - path.node.left.object.object.name === 'module' + t.isIdentifier(node.callee) && + node.callee.name === 'require' ) { - if (!moduleBinding) { - state.isCJS = true; + // Require must be global for us to consider this a CommonJS + // module. + this.state.isCJS = true; + + // Normalize the string value, default to the standard string + // literal format of `{ value: "" }`. + let source = getStaticValue(node.arguments[0]); + + if (source === false) { + console.warn( + `Dynamic requires are not currently supported: ${path.toString()}. please configure dynamicrequiretargets` + ); + return; } - } else if ( - t.isIdentifier(path.node.left.object) && - path.node.left.object.name === 'module' - ) { - if (!moduleBinding) { - state.isCJS = true; - // Looking at a re-exports, handled above. - if (t.isCallExpression(path.node.right)) { - return; + const specifiers = []; + let {parentPath} = path; + let {node: parentNode} = parentPath; + + let childScopeRequireNames = null; + + if (!t.isProgram(path.scope.path)) { + childScopeRequireNames = + this.state.childScopeRequires.get(source); + if (!childScopeRequireNames) { + childScopeRequireNames = new Set(); + this.state.childScopeRequires.set( + source, + childScopeRequireNames + ); } } - } else if (path.node.left.object.name === 'exports') { - // Check for regular exports - const {name} = path.node.left.property; - if ( - exportsBinding || - // If export is named "default" leave as is. - // It is not possible to export "default" as a named export. - // e.g. `export.default = 'a'` - name === 'default' - ) { - return; - } - state.isCJS = true; + // Convert to named import. + // let {a} = require('a') + if (t.isObjectPattern(parentNode.id)) { + if (childScopeRequireNames) { + parentNode.id.properties.forEach((prop) => { + childScopeRequireNames.add(prop.key); + }); + return; + } + + parentNode.id.properties.forEach((prop) => { + specifiers.push( + t.importSpecifier( + t.identifier(prop.value), + t.identifier(prop.key) + ) + ); + }); + } else if (t.isMemberExpression(parentNode)) { + // let a = require('a')[a],属于动态导入 + if (parentNode.computed) { + console.warn( + `Dynamic requires are not currently supported: ${path.toString()}. please configure dynamicrequiretargets` + ); - let prop = path.node.right; + return; + } - if ( - (path.scope - .getProgramParent() - .hasBinding(prop.name) || - state.globals.has(prop.name)) && - // Don't rename `undefined`. - prop.name !== 'undefined' - ) { - prop = path.scope.generateUidIdentifier(prop.name); + if (childScopeRequireNames) { + childScopeRequireNames.add( + parentNode.property.key + ); + return; + } - const oldName = path.node.right.name; - state.renamed.set(oldName, prop.name); + specifiers.push( + t.importSpecifier( + t.identifier(parentNode.property.name), + t.identifier(parentNode.property.name) + ) + ); + } else if (source) { + // Convert to default import. + if (childScopeRequireNames) { + childScopeRequireNames.add('default'); + return; + } - // Add this new identifier into the globals and replace the - // right hand side with this replacement. - state.globals.add(prop.name); - path.get('right').replaceWith(prop); - path.scope.rename(oldName, prop.name); + let declaratorParentPath = path.find((path) => { + return t.isVariableDeclarator(path); + }); + + let name = + (declaratorParentPath.node.id && + declaratorParentPath.node.id.name) || + ''; + let id = name + ? t.identifier(name) + : path.scope.generateUidIdentifier(); + + // 由 require 转换的 import default 节点 + // 标记 + // 当 tree shake 时,对于这类节点: + // 1. 这类节点默认在本文件使用 + // 2. 当找到依赖文件时,依赖文件的 $t_cjs_temp_export(exports 转换的 export 节点)节点默认全部被有效 import + let defaultImportNode = + t.importDefaultSpecifier(id); + + this.markNodeDeep( + defaultImportNode, + '$t_cjs_temp_default_import' + ); + specifiers.push(defaultImportNode); } - // If we set an invalid name, then abort out. - try { - // Ensure that the scope is clean before we inject new, - // potentially conflicting, variables. - const newName = - path.scope.generateUidIdentifier(name).name; + const importDeclaration = t.importDeclaration( + specifiers, + t.stringLiteral(source) + ); - path.scope.rename(name, newName); + this.state.globalESMImports.set(importDeclaration, [ + path.find((path) => { + return t.isProgram(path.parentPath); + }), + ]); + } + }, + }, - // Check if this name is reserved, if so, then bail out. - if (check(name)) { - return; - } + ModuleDeclaration: { + enter: () => { + this.state.isESM = true; + }, + }, + + AssignmentExpression: { + enter: (path) => { + if (path.node.$t_ignore) { + return; + } + + path.node.$t_ignore = true; - const decl = t.exportNamedDeclaration( - t.variableDeclaration('let', [ - t.variableDeclarator( - path.node.left.property, - t.memberExpression( - t.identifier('exports'), - path.node.left.property - ) + let generateExportNode = (path, name) => { + let exportName = name; + let rightNode = path.node.right; + + if (t.isIdentifier(rightNode)) { + let exportNamedDeclaration = + t.exportNamedDeclaration(null, [ + t.exportSpecifier( + t.identifier(rightNode.name), + t.identifier(exportName) ), - ]), - [] + ]); + this.state.globalESMExports.set( + exportNamedDeclaration, + [ + path.find((path) => { + return t.isProgram(path.parentPath); + }), + ] ); + } else { + let id = + path.scope.generateUidIdentifierBasedOnNode( + rightNode, + exportName + ); + let declaration = t.variableDeclaration('let', [ + t.variableDeclarator(id, rightNode), + ]); + let declarationPath = + path.insertBefore(declaration)[0]; + + let rightPath = path.get('right'); + rightPath.replaceWith(id); + + let exportNamedDeclaration = + t.exportNamedDeclaration(null, [ + t.exportSpecifier( + id, + t.identifier(exportName) + ), + ]); + this.state.globalESMExports.set( + exportNamedDeclaration, + [ + path.find((path) => { + return t.isProgram(path.parentPath); + }), + ] + ); + } + }; + + // Check for module.exports. + // 只处理顶级作用域 + // 只处理纯粹的 exports.a=1 语句 + // 即不嵌套在任何其他语句中 + if ( + t.isMemberExpression(path.node.left) && + t.isProgram(path.scope.path) && + t.isProgram(path.parentPath.parentPath) + ) { + const moduleBinding = path.scope.getBinding('module'); + const exportsBinding = path.scope.getBinding('exports'); + + // Something like `module.exports.namedExport = true;`. + if ( + t.isMemberExpression(path.node.left.object) && + path.node.left.object.object.name === 'module' + ) { + if (moduleBinding) { + return; + } + + this.state.isCJS = true; + + if ( + getStaticMemberProValue( + path.node.left.object + ) === 'exports' + ) { + let name = getStaticMemberProValue( + path.node.left + ); + + // 动态导出,不转换 + if (name === false) { + return; + } - if (!state.identifiers.has(name)) { - path.scope - .getProgramParent() - .path.pushContainer('body', decl); - state.identifiers.add(name); + generateExportNode(path, name); + } + } else if (path.node.left.object.name === 'exports') { + // Check for regular exports + let name = getStaticMemberProValue(path.node.left); + if ( + exportsBinding || + // If export is named "default" leave as is. + // It is not possible to export "default" as a named export. + // e.g. `export.default = 'a'` + // 动态导出和默认导出,不转换 + name === 'default' || + name === false + ) { + return; } - } catch {} + + this.state.isCJS = true; + + generateExportNode(path, name); + } } - } + }, }, - }, - }); -} -let code = readFile(path.resolve(__dirname, './transform-test.js')); -let ast = parseESCode(code); + MemberExpression: { + enter: (path) => { + if ( + path.node.$t_ignore2 || + this.state.isDynamicUsedExportsProperty + ) { + return; + } + + path.node.$t_ignore2 = true; + + const moduleBinding = path.scope.getBinding('module'); + const exportsBinding = path.scope.getBinding('exports'); + + let addUsedExports = () => { + let exportsProVal = getStaticMemberProValue(path.node); + + // 动态访问了 exports 上的属性 + if (exportsProVal === false) { + this.state.isDynamicUsedExportsProperty = true; + return; + } + + this.state.usedExports.add(exportsProVal); + }; + + let checkIsAssignmentExpressionLeft = () => { + let parentPath = path.parentPath; + let leftPath = parentPath.get('left'); + return leftPath === path; + }; + + if ( + t.isMemberExpression(path.node.object) && + path.node.object.object.name === 'module' + ) { + if (moduleBinding) { + return; + } + + if (checkIsAssignmentExpressionLeft()) { + return; + } + + let staticModuleProVal = getStaticMemberProValue( + path.node.object + ); + + // 动态访问了module上的属性 + // 无法确切的知道是否访问了exports属性 + // 进而无法知道访问了exports的哪些属性 + if (staticModuleProVal === false) { + this.state.isDynamicUsedExportsProperty = true; + return; + } + + if (staticModuleProVal !== 'exports') { + return; + } + + addUsedExports(); + } else if (path.node.object.name === 'exports') { + if (exportsBinding) { + return; + } -transform(ast); + if (checkIsAssignmentExpressionLeft()) { + return; + } + + addUsedExports(); + } + }, + }, + }); + } +} -const {code: outputCode} = generate( - ast, - { - /* options */ - decoratorsBeforeExport: true, - }, - code -); +module.exports = { + TransformCommonJs, +}; -writeFile( - path.resolve(path.resolve(__dirname, './transform-test-a.js')), - outputCode -); +// let src = path.resolve(__dirname, './transform-test.js'); +// let code = readFile(src); + +// console.time('transform'); +// let tt = new TransformCommonJs({src, code}); +// console.timeEnd('transform'); + +// const {code: outputCode} = generate( +// tt.ast, +// { +// /* options */ +// decoratorsBeforeExport: true, +// }, +// code +// ); + +// writeFile( +// path.resolve(path.resolve(__dirname, './transform-test-a.js')), +// outputCode +// ); diff --git a/packages/wxa-cli/src/tree-shake/transform-test-a.js b/packages/wxa-cli/src/tree-shake/transform-test-a.js deleted file mode 100644 index f35bc664..00000000 --- a/packages/wxa-cli/src/tree-shake/transform-test-a.js +++ /dev/null @@ -1,245 +0,0 @@ -'use strict'; - -import _packageJson from "../package.json"; -import _crypto2 from "crypto"; -import _fsCache2 from "./fs-cache"; -import _mkdirp2 from "mkdirp"; -import _path2 from "path"; -import _fs2 from "fs"; -import _chalk2 from "chalk"; -import _babelRuntimeHelpersInteropRequireDefault from "@babel/runtime/helpers/interopRequireDefault"; -var module = { - exports: {} -}; -var exports = module.exports; -let _interopRequireDefault = _babelRuntimeHelpersInteropRequireDefault; -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.getFiles = _getFiles; // exports.getConfig = getConfig; - -exports.readFile = _readFile; -exports.writeFile = _writeFile; -exports.isFile = _isFile; -exports.isDir = _isDir; -exports.getRelative = _getRelative; -exports.getDistPath = _getDistPath; -exports.copy = _copy; -exports.amazingCache = _amazingCache; -exports.applyPlugins = _applyPlugins; -exports.isEmpty = _isEmpty; -exports.getHash = _getHash; -exports.getHashWithString = _getHashWithString; -exports.promiseSerial = _promiseSerial; -exports.getClassSet = _getClassSet; -exports.addClass = _addClass; -exports.removeClass = _removeClass; - -let _chalk = _interopRequireDefault(_chalk2); - -let _fs = _interopRequireDefault(_fs2); - -let _path = _interopRequireDefault(_path2); - -let _mkdirp = _interopRequireDefault(_mkdirp2); - -let _fsCache = _interopRequireDefault(_fsCache2); - -let _crypto = _interopRequireDefault(_crypto2); - -let current = process.cwd(); -let pkg = _packageJson; - -function _getFiles(dir = process.cwd(), prefix = '') { - dir = _path.default.normalize(dir); - let rst = []; - exports.ttt = 1; - - if (!_fs.default.existsSync(dir)) { - return rst; - } - - let files = _fs.default.readdirSync(dir); - - files.forEach(item => { - let filepath = dir + _path.default.sep + item; - - let stat = _fs.default.statSync(filepath); - - if (stat.isFile()) { - rst.push(prefix + item); - } else if (stat.isDirectory()) { - rst = rst.concat(_getFiles(filepath, _path.default.normalize(prefix + item + _path.default.sep))); - } - }); - return rst; -} // function getConfig() { -// let configPath = _path.default.join(process.cwd(), 'wxa.config.js'); -// let config = require(configPath); -// return config; -// } - - -function _readFile(p) { - let rst = ''; - p = typeof p === 'object' ? _path.default.join(p.dir, p.base) : p; - - try { - rst = _fs.default.readFileSync(p, 'utf-8'); - } catch (e) { - rst = null; - } - - return rst; -} - -function _writeFile(p, data) { - let opath = typeof p === 'string' ? _path.default.parse(p) : p; - - _mkdirp.default.sync(opath.dir); - - _fs.default.writeFileSync(p, data); -} - -function _isFile(p) { - p = typeof p === 'object' ? _path.default.join(p.dir, p.base) : p; - if (!_fs.default.existsSync(p)) return false; - return _fs.default.statSync(p).isFile(); -} - -function _isDir(p) { - // console.log(isDir, fs.existsSync(p), p); - if (!_fs.default.existsSync(p)) { - return false; - } - - return _fs.default.statSync(p).isDirectory(); -} - -function _getRelative(opath) { - return _path.default.relative(current, _path.default.join(opath.dir, opath.base)); -} - -function _getDistPath(opath, ext, src, dist) { - let relative; - opath = typeof opath === 'string' ? _path.default.parse(opath) : opath; - ext = ext ? ext[0] === '.' ? ext : '.' + ext : opath.ext; - - if (_path.default.relative(current, opath.dir).indexOf('node_modules') === 0) { - relative = _path.default.relative(_path.default.join(current, 'node_modules'), opath.dir); - relative = _path.default.join('npm', relative); - } else { - relative = _path.default.relative(_path.default.join(current, src), opath.dir); - } - - return _path.default.join(current, dist, relative, opath.name + ext); -} - -function _copy(from, to) { - return new Promise((resolve, reject) => { - _mkdirp.default.sync(_path.default.parse(to).dir); - - _fs.default.copyFile(from, to, err => { - if (err) return reject(err); - resolve(); - }); - }); -} - -function _amazingCache(params, needCache) { - let defaultOpts = { - directory: true, - identifier: JSON.stringify({ - '@wxa/cli2': pkg.version, - 'env': process.env.NODE_ENV || 'development' - }) - }; - let cacheParams = Object.assign({}, defaultOpts, params); - - if (needCache) { - return (0, _fsCache.default)(cacheParams); - } else { - let { - source, - transform, - options - } = cacheParams; - return transform(source, options); - } -} - -function _applyPlugins(plugins, compiler) { - if (plugins == null) return; // console.log(plugins); - - if (typeof plugins !== 'object') { - throw new Error('wxa配置文件有误,plugins'); - } - - if (!Array.isArray(plugins)) plugins = [plugins]; - plugins.forEach(plugin => plugin.apply(compiler)); -} - -function _isEmpty(n) { - return n == null || n === ''; -} - -function _getHash(filepath) { - let content = _readFile(filepath); - - return content == null ? Date.now() : _crypto.default.createHash('md5').update(content).digest('hex'); -} - -function _getHashWithString(content) { - return content == null ? Date.now() : _crypto.default.createHash('md5').update(content).digest('hex'); -} - -function _promiseSerial(funs) { - return funs.reduce((promise, fun) => { - return promise.then(result => fun().then(Array.prototype.concat.bind(result))); - }, Promise.resolve([])); -} - -function _getClassSet(classStr) { - let classList = []; - - if (classStr && typeof classStr === 'string') { - classList = classStr.split(' '); - } - - return new Set(classList); -} - -function _addClass(classStr, newClass) { - let classSet = _getClassSet(classStr); - - classSet.add(newClass); - return Array.from(classSet); -} - -function _removeClass(classStr, destClass) { - let classSet = _getClassSet(classStr); - - classSet.delete(destClass); - return Array.from(classSet); -} // # sourceMappingURL=utils.js.map - - -export let getFiles = exports.getFiles; -export let readFile = exports.readFile; -export let writeFile = exports.writeFile; -export let isFile = exports.isFile; -export let isDir = exports.isDir; -export let getRelative = exports.getRelative; -export let getDistPath = exports.getDistPath; -export let copy = exports.copy; -export let amazingCache = exports.amazingCache; -export let applyPlugins = exports.applyPlugins; -export let isEmpty = exports.isEmpty; -export let getHash = exports.getHash; -export let getHashWithString = exports.getHashWithString; -export let promiseSerial = exports.promiseSerial; -export let getClassSet = exports.getClassSet; -export let addClass = exports.addClass; -export let removeClass = exports.removeClass; -export let ttt = exports.ttt; -export default module.exports; \ No newline at end of file diff --git a/packages/wxa-cli/src/tree-shake/transform-test.js b/packages/wxa-cli/src/tree-shake/transform-test.js deleted file mode 100644 index a386ef7a..00000000 --- a/packages/wxa-cli/src/tree-shake/transform-test.js +++ /dev/null @@ -1,233 +0,0 @@ -'use strict'; - -let _interopRequireDefault = require('@babel/runtime/helpers/interopRequireDefault'); - -Object.defineProperty(exports, '__esModule', { - value: true, -}); -exports.getFiles = getFiles; -// exports.getConfig = getConfig; -exports.readFile = readFile; -exports.writeFile = writeFile; -exports.isFile = isFile; -exports.isDir = isDir; -exports.getRelative = getRelative; -exports.getDistPath = getDistPath; -exports.copy = copy; -exports.amazingCache = amazingCache; -exports.applyPlugins = applyPlugins; -exports.isEmpty = isEmpty; -exports.getHash = getHash; -exports.getHashWithString = getHashWithString; -exports.promiseSerial = promiseSerial; -exports.getClassSet = getClassSet; -exports.addClass = addClass; -exports.removeClass = removeClass; - -let _chalk = _interopRequireDefault(require('chalk')); - -let _fs = _interopRequireDefault(require('fs')); - -let _path = _interopRequireDefault(require('path')); - -let _mkdirp = _interopRequireDefault(require('mkdirp')); - -let _fsCache = _interopRequireDefault(require('./fs-cache')); - -let _crypto = _interopRequireDefault(require('crypto')); - -let current = process.cwd(); - -let pkg = require('../package.json'); - -function getFiles(dir = process.cwd(), prefix = '') { - dir = _path.default.normalize(dir); - let rst = []; - - exports.ttt= 1; - - if (!_fs.default.existsSync(dir)) { - return rst; - } - - let files = _fs.default.readdirSync(dir); - - files.forEach((item) => { - let filepath = dir + _path.default.sep + item; - - let stat = _fs.default.statSync(filepath); - - if (stat.isFile()) { - rst.push(prefix + item); - } else if (stat.isDirectory()) { - rst = rst.concat( - getFiles( - filepath, - _path.default.normalize(prefix + item + _path.default.sep) - ) - ); - } - }); - return rst; -} - -// function getConfig() { -// let configPath = _path.default.join(process.cwd(), 'wxa.config.js'); - -// let config = require(configPath); - -// return config; -// } - -function readFile(p) { - let rst = ''; - p = typeof p === 'object' ? _path.default.join(p.dir, p.base) : p; - - try { - rst = _fs.default.readFileSync(p, 'utf-8'); - } catch (e) { - rst = null; - } - - return rst; -} - -function writeFile(p, data) { - let opath = typeof p === 'string' ? _path.default.parse(p) : p; - - _mkdirp.default.sync(opath.dir); - - _fs.default.writeFileSync(p, data); -} - -function isFile(p) { - p = typeof p === 'object' ? _path.default.join(p.dir, p.base) : p; - if (!_fs.default.existsSync(p)) return false; - return _fs.default.statSync(p).isFile(); -} - -function isDir(p) { - // console.log(isDir, fs.existsSync(p), p); - if (!_fs.default.existsSync(p)) { - return false; - } - - return _fs.default.statSync(p).isDirectory(); -} - -function getRelative(opath) { - return _path.default.relative( - current, - _path.default.join(opath.dir, opath.base) - ); -} - -function getDistPath(opath, ext, src, dist) { - let relative; - opath = typeof opath === 'string' ? _path.default.parse(opath) : opath; - ext = ext ? (ext[0] === '.' ? ext : '.' + ext) : opath.ext; - - if ( - _path.default.relative(current, opath.dir).indexOf('node_modules') === 0 - ) { - relative = _path.default.relative( - _path.default.join(current, 'node_modules'), - opath.dir - ); - relative = _path.default.join('npm', relative); - } else { - relative = _path.default.relative( - _path.default.join(current, src), - opath.dir - ); - } - - return _path.default.join(current, dist, relative, opath.name + ext); -} - -function copy(from, to) { - return new Promise((resolve, reject) => { - _mkdirp.default.sync(_path.default.parse(to).dir); - - _fs.default.copyFile(from, to, (err) => { - if (err) return reject(err); - resolve(); - }); - }); -} - -function amazingCache(params, needCache) { - let defaultOpts = { - directory: true, - identifier: JSON.stringify({ - '@wxa/cli2': pkg.version, - 'env': process.env.NODE_ENV || 'development', - }), - }; - let cacheParams = Object.assign({}, defaultOpts, params); - - if (needCache) { - return (0, _fsCache.default)(cacheParams); - } else { - let {source, transform, options} = cacheParams; - return transform(source, options); - } -} - -function applyPlugins(plugins, compiler) { - if (plugins == null) return; // console.log(plugins); - - if (typeof plugins !== 'object') { -throw new Error('wxa配置文件有误,plugins'); -} - if (!Array.isArray(plugins)) plugins = [plugins]; - plugins.forEach((plugin) => plugin.apply(compiler)); -} - -function isEmpty(n) { - return n == null || n === ''; -} - -function getHash(filepath) { - let content = readFile(filepath); - return content == null - ? Date.now() - : _crypto.default.createHash('md5').update(content).digest('hex'); -} - -function getHashWithString(content) { - return content == null - ? Date.now() - : _crypto.default.createHash('md5').update(content).digest('hex'); -} - -function promiseSerial(funs) { - return funs.reduce((promise, fun) => { - return promise.then((result) => - fun().then(Array.prototype.concat.bind(result)) - ); - }, Promise.resolve([])); -} - -function getClassSet(classStr) { - let classList = []; - - if (classStr && typeof classStr === 'string') { - classList = classStr.split(' '); - } - - return new Set(classList); -} - -function addClass(classStr, newClass) { - let classSet = getClassSet(classStr); - classSet.add(newClass); - return Array.from(classSet); -} - -function removeClass(classStr, destClass) { - let classSet = getClassSet(classStr); - classSet.delete(destClass); - return Array.from(classSet); -} -// # sourceMappingURL=utils.js.map From f6bea1e60cb4651da397a3eb05293e533a337a4a Mon Sep 17 00:00:00 2001 From: sparklinm Date: Sun, 20 Jun 2021 22:09:14 +0800 Subject: [PATCH 10/20] =?UTF-8?q?feat:=20=E4=BD=BF=E7=94=A8path.scope?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/.eslintrc.json | 3 +- packages/wxa-cli/example/expDFOF/index.js | 6 +- packages/wxa-cli/example/index.js | 8 +- packages/wxa-cli/example/shaking/cjs1.js | 6 +- packages/wxa-cli/example/shaking/cjs2.js | 3 + packages/wxa-cli/example/shaking/index.js | 27 +- packages/wxa-cli/example/shaking/user.js | 18 +- packages/wxa-cli/example/user.js | 8 +- packages/wxa-cli/src/tree-shake/graph.js | 389 +++++++++--------- packages/wxa-cli/src/tree-shake/index.js | 197 ++++----- .../src/tree-shake/tansform-commonJS.js | 24 +- packages/wxa-cli/src/tree-shake/util.js | 50 +++ 12 files changed, 392 insertions(+), 347 deletions(-) diff --git a/packages/wxa-cli/.eslintrc.json b/packages/wxa-cli/.eslintrc.json index e5b78f4a..7d1e7515 100644 --- a/packages/wxa-cli/.eslintrc.json +++ b/packages/wxa-cli/.eslintrc.json @@ -27,7 +27,8 @@ "no-trailing-spaces": "off", "require-jsdoc": "off", "camelcase": "warn", - "no-invalid-this": "warn" + "no-invalid-this": "warn", + "linebreak-style": ["off", "windows"] }, "plugins": [] } diff --git a/packages/wxa-cli/example/expDFOF/index.js b/packages/wxa-cli/example/expDFOF/index.js index 47ab447c..6be76333 100644 --- a/packages/wxa-cli/example/expDFOF/index.js +++ b/packages/wxa-cli/example/expDFOF/index.js @@ -15,11 +15,13 @@ export {o1 as o11, o2}; // export {default} from '' // export {a as default} from '' // export * as default from '' -// export default function() {} -// export default {} // export {a as default} // let p1 = 1 // export default p1 +// export default 1 +// export default a=1 +// export default function() {} +// export default {} // 导出全部 export * from ''; diff --git a/packages/wxa-cli/example/index.js b/packages/wxa-cli/example/index.js index 95802b95..ad6a6836 100644 --- a/packages/wxa-cli/example/index.js +++ b/packages/wxa-cli/example/index.js @@ -10,6 +10,7 @@ isFile(); getName(); +let ssqqww =1; console.log(user); let a = {x: 1}, @@ -21,6 +22,8 @@ function m(x = 1, y) { t = 9; t + 5; let qqq = 10; + let ssqqww =5; + console.log(ssqqww); } m(); @@ -63,12 +66,14 @@ let obj = { // m, // age, // }; + +export let qwe=1, rty=2; export function getName() {} // export {m as qqqqq, a as default}; // export {x, y} from './a'; -export default function() {} +// export default function asf() {}; export {Myclass}; // eslint-disable-next-line no-var @@ -76,5 +81,6 @@ export {Myclass}; export {mm as ttttttt}; export {getName as tttt} from './user'; +export {default} from './user'; export * as tttttt from './user'; diff --git a/packages/wxa-cli/example/shaking/cjs1.js b/packages/wxa-cli/example/shaking/cjs1.js index 8410bbe5..e14a0de4 100644 --- a/packages/wxa-cli/example/shaking/cjs1.js +++ b/packages/wxa-cli/example/shaking/cjs1.js @@ -10,7 +10,7 @@ module.exports = { getFiles, }; -function getFiles(dir = process.cwd(), prefix = '') { +function getFiles() { let rst = []; exports.rst = rst; // exports[aaaa] = aaaa; // let ttt= require('sss'); @@ -25,6 +25,6 @@ function getFiles(dir = process.cwd(), prefix = '') { // } -function writeFile(p, data) {} +function writeFile() {} -function isFile(p) {} +function isFile() {} diff --git a/packages/wxa-cli/example/shaking/cjs2.js b/packages/wxa-cli/example/shaking/cjs2.js index e69de29b..3e913ad3 100644 --- a/packages/wxa-cli/example/shaking/cjs2.js +++ b/packages/wxa-cli/example/shaking/cjs2.js @@ -0,0 +1,3 @@ +function fn1() {} + +exports.fn1 = fn1; \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/index.js b/packages/wxa-cli/example/shaking/index.js index 69184d60..b01cb479 100644 --- a/packages/wxa-cli/example/shaking/index.js +++ b/packages/wxa-cli/example/shaking/index.js @@ -1,9 +1,11 @@ /* eslint-disable one-var */ import './user'; import * as user from './user'; +import './user'; import {writeFile, isFile} from './cjs1'; writeFile(); isFile(); +getName(); console.log(user); let a = { x: 1, @@ -11,15 +13,17 @@ let a = { n = 1; let t = 10; -function m(x = 1, y) { +function m() { a = 5; ++a; t = 9; t + 5; + let ssqqww = 5; + console.log(ssqqww); } m(); -[1, 2, 3].forEach(function(item) {}); +[1, 2, 3].forEach(function() {}); for (i = 0; i < 100; i++) {} @@ -28,10 +32,12 @@ class Myclass { [n] = () => {}; } -export function mm() {} +function mm() {} + +export {mm}; mm(); -(function(x, y) {})(); // export default { +(function() {})(); // export default { // x: 1, // t() { // }, @@ -40,12 +46,19 @@ mm(); // }; -export function getName() {} // export {m as qqqqq, a as default}; -// export {x, y} from './a'; +let qwe = 1, + rty = 2; +export {qwe, rty}; -export default function() {} +function getName() {} + +export {getName}; +// export {m as qqqqq, a as default}; +// export {x, y} from './a'; +// export default function asf() {}; export {Myclass}; // eslint-disable-next-line no-var export {mm as ttttttt}; export {getName as tttt} from './user'; +export {default} from './user'; export * as tttttt from './user'; diff --git a/packages/wxa-cli/example/shaking/user.js b/packages/wxa-cli/example/shaking/user.js index 8c0a6fbd..30abbdf1 100644 --- a/packages/wxa-cli/example/shaking/user.js +++ b/packages/wxa-cli/example/shaking/user.js @@ -1,6 +1,16 @@ -export function getName() {} // export default function getUser(params) { +function getName() {} + +export {getName}; +// export default function getUser(params) { // } +let a = 1; +export default a; // eslint-disable-next-line one-var + +let mm1 = 1, + c = function mm2() {}; + +export {mm1, c}; + +function fn2() {} -// eslint-disable-next-line one-var -export let mm1 = 1, - c = function mm2(params) {}; +export {fn2}; diff --git a/packages/wxa-cli/example/user.js b/packages/wxa-cli/example/user.js index 3b5a254a..1a9d9326 100644 --- a/packages/wxa-cli/example/user.js +++ b/packages/wxa-cli/example/user.js @@ -11,5 +11,11 @@ export default a; // eslint-disable-next-line one-var export let mm1 =1, c=function mm2(params) { - }; + +function fn2(params) { + +} + +export {fn2}; + diff --git a/packages/wxa-cli/src/tree-shake/graph.js b/packages/wxa-cli/src/tree-shake/graph.js index d5b57acf..fccae28b 100644 --- a/packages/wxa-cli/src/tree-shake/graph.js +++ b/packages/wxa-cli/src/tree-shake/graph.js @@ -1,6 +1,6 @@ const traverse = require('@babel/traverse').default; -const {Scope} = require('./scope'); -const {readFile, resolveDepSrc, parseESCode} = require('./util'); +const t = require('@babel/types'); +const {readFile, resolveDepSrc, parseESCode, dceDeclaration} = require('./util'); let {TransformCommonJs} = require('./tansform-commonJS'); class Graph { @@ -21,9 +21,6 @@ class Graph { s += '.js'; } - // console.log('--------'); - // console.log(s); - return s; } @@ -39,169 +36,172 @@ class Graph { return expSrc; } - collectDeclaration(path, scope) { - function addToScope(node, attr, isBlockDeclaration = false) { - let identifierNode = node[attr]; - - // 类似于export default function(){} - // 这类声明也不能在本文件内使用,直接忽略 - if (!identifierNode || !identifierNode.name) { - return; - } - - identifierNode._skip = true; - - node._usedByNodes = []; - scope.add(node, identifierNode.name, isBlockDeclaration); - } - - let {node} = path; - let childScope; - - switch (node.type) { - // 函数声明 function a(){} - case 'FunctionDeclaration': - childScope = new Scope({ - parent: scope, - block: false, - }); - addToScope(node, 'id', false); - // 箭头函数 ()=>{} - case 'ArrowFunctionExpression': - // 函数表达式 function(){} - case 'FunctionExpression': - childScope = new Scope({ - parent: scope, - block: false, - }); - break; - // 块级作用域{} - case 'BlockStatement': - childScope = new Scope({ - parent: scope, - block: true, - }); - break; - // 变量声明 - case 'VariableDeclaration': - node.declarations.forEach((variableDeclarator) => { - if (node.kind === 'let' || node.kind === 'const') { - addToScope(variableDeclarator, 'id', true); - } else { - addToScope(variableDeclarator, 'id', false); - } - }); - break; - // 类的声明 - case 'ClassDeclaration': - addToScope(node, 'id', true); - break; - // import 的声明 - case 'ImportDeclaration': - node.specifiers.forEach((specifier) => { - if (node.$t_cjs_temp_import) { - return; - } - addToScope(specifier, 'local', true); - }); - break; - } - - return childScope; - } + collectImport(src) { + let imports = {}; + let store = (name, path, node) => { + let impSrc = this.getAbsolutePath(src, node.source.value); + imports[impSrc] = imports[impSrc] || {}; + imports[impSrc][name] = path; + }; - collectImport(path) { - let {node} = path; - let importInfo = null; - - switch (node.type) { - // import 的声明 - case 'ImportDeclaration': - importInfo = {}; - node.specifiers.forEach((specifier) => { - let name = specifier.imported && specifier.imported.name; - if (!name) { - if (specifier.type === 'ImportDefaultSpecifier') { - name = 'default'; - } else if ( - specifier.type === 'ImportNamespaceSpecifier' - ) { - name = '*'; + let visitor = { + ImportDeclaration: { + enter: (path) => { + let {node} = path; + let specifierPaths = path.get('specifiers'); + specifierPaths.forEach((specifierPath) => { + let specifierNode = specifierPath.node; + let name = + specifierNode.imported && + specifierNode.imported.name; + + if (!name) { + if ( + specifierNode.type === 'ImportDefaultSpecifier' + ) { + name = 'default'; + } else if ( + specifierNode.type === + 'ImportNamespaceSpecifier' + ) { + name = '*'; + } } - } - importInfo[name] = specifier; - }); - break; - } + store(name, specifierPath, node); + }); + }, + }, + }; - return importInfo; + return {visitor, imports}; } - collectExport(path, isRoot) { - let {node} = path; - let exportInfo = null; + collectExport(src, isRoot) { + let exports = {}; - let markShakingFlag = (node) => { + let store = (name, path, node) => { if (isRoot) { - node._shake = 0; + path._shake = 0; } else { - node._shake = 1; + path._shake = 1; } + let expSrc = this.getExpSrc(node, src); + exports[expSrc] = exports[expSrc] || {}; + exports[expSrc][name] = path; }; - switch (node.type) { - // export 的声明 - case 'ExportNamedDeclaration': - exportInfo = {}; - if (node.specifiers && node.specifiers.length) { - node.specifiers.forEach((specifier) => { - let name = specifier.exported.name; - exportInfo[name] = specifier; - markShakingFlag(specifier); - }); - } else { - let declaration = node.declaration; - - if (declaration.type === 'FunctionDeclaration') { - let name = declaration.id.name; - exportInfo[name] = declaration; - declaration._shake = 1; - markShakingFlag(declaration); - } else if (declaration.type === 'VariableDeclaration') { - declaration.declarations.forEach( - (variableDeclarator) => { - let name = variableDeclarator.id.name; - exportInfo[name] = variableDeclarator; - markShakingFlag(variableDeclarator); - } + let storeSpecifiers = (path, node) => { + let specifierPaths = path.get('specifiers'); + specifierPaths.forEach((specifierPath) => { + let name = specifierPath.node.exported.name; + store(name, specifierPath, node); + }); + }; + + let transformExportDeclarationToSpecifiers = (path) => { + let declarationPath = path.get('declaration'); + let declarationNode = declarationPath.node; + let specifiers = []; + + if (declarationNode.type === 'FunctionDeclaration') { + let name = declarationNode.id.name; + specifiers.push( + t.exportSpecifier(t.identifier(name), t.identifier(name)) + ); + } else if (declarationNode.type === 'VariableDeclaration') { + let declarationPaths = declarationPath.get('declarations'); + declarationPaths.forEach((variableDeclaratorPath) => { + let name = variableDeclaratorPath.node.id.name; + specifiers.push( + t.exportSpecifier( + t.identifier(name), + t.identifier(name) + ) + ); + }); + } else if (declarationNode.type === 'ClassDeclaration') { + let name = declarationNode.id.name; + specifiers.push( + t.exportSpecifier(t.identifier(name), t.identifier(name)) + ); + } + + return {specifiers, declarationNode}; + }; + + let visitor = { + ExportNamedDeclaration: { + enter: (path) => { + let {node} = path; + + if (node.specifiers && node.specifiers.length) { + storeSpecifiers(path, node); + } else { + let {specifiers, declarationNode} = + transformExportDeclarationToSpecifiers(path); + + path.insertBefore(declarationNode); + let exportNamedDeclaration = t.exportNamedDeclaration( + null, + specifiers ); - } else if (declaration.type === 'ClassDeclaration') { - let name = declaration.id.name; - exportInfo[name] = declaration; - markShakingFlag(declaration); + let newExportPath = path.insertAfter( + exportNamedDeclaration + )[0]; + path.remove(); + + storeSpecifiers(newExportPath, node); + } + }, + }, + ExportDefaultDeclaration: { + enter: (path) => { + let {node} = path; + let declarationNode = node.declaration; + let exportPath = path; + + // TODO,未处理 export default a=1 这类表达式 + // 类似于export default function mm(){} + // 单独声明mm,并export default {mm} + if (declarationNode.id && declarationNode.id.name) { + path.insertBefore(declarationNode); + let exportDefaultNode = t.exportDefaultDeclaration( + t.objectExpression([ + t.objectProperty( + t.identifier(declarationNode.id.name), + t.identifier(declarationNode.id.name) + ), + ]) + ); + exportPath = path.insertAfter(exportDefaultNode)[0]; + path.remove(); } - } - break; - case 'ExportDefaultDeclaration': - exportInfo = {}; - let declaration = node.declaration; - - if (declaration) { - exportInfo.default = declaration; - } else { - exportInfo.default = node; - } - markShakingFlag(exportInfo.default); - break; - case 'ExportAllDeclaration': - exportInfo = {}; - exportInfo['*'] = node; - markShakingFlag(node); - break; - } + store('default', exportPath, node); + }, + }, + ExportAllDeclaration: { + enter: (path) => { + let {node} = path; + store('*', path, node); + }, + }, + }; + + return {visitor, exports}; + } - return exportInfo; + dceDeclaration(ast) { + let currentScope = null; + traverse(ast, { + enter: (path) => { + let scope = path.scope; + if (currentScope !== scope) { + currentScope = scope; + dceDeclaration(currentScope); + } + }, + }); } analysis() { @@ -218,60 +218,39 @@ class Graph { content = entry.content; } - // if (src.endsWith('safe-area-inset\\index.js')) { + // if (src.endsWith('user.js')) { // console.log('src', src); + // this.debug = true; // } if (analyzedFile[src]) { return analyzedFile[src]; } + + console.log('---'); + console.log(src); - // console.log(src); - - let imports = {}; - let exports = {}; let code = content || readFile(src); let ast = parseESCode(code); - let transformCommonJs = new TransformCommonJs({src, code, ast}); + this.dceDeclaration(ast); - let scope = new Scope(); + let topScope = null; + let transformCommonJs = new TransformCommonJs({src, code, ast}); + let {visitor: exportVisitor, exports} = this.collectExport( + src, + isRoot + ); + let {visitor: importVisitor, imports} = this.collectImport(src); traverse(ast, { - enter: (path) => { - let {node} = path; - - let childScope = this.collectDeclaration(path, scope); - if (childScope) { - node._scope = childScope; - scope = childScope; - } - - let importInfo = this.collectImport(path); - if (importInfo) { - let impSrc = this.getAbsolutePath( - src, - node.source.value - ); - imports[impSrc] = imports[impSrc] || {}; - imports[impSrc] = {...imports[impSrc], ...importInfo}; - } - - let exportInfo = this.collectExport(path, isRoot); - if (exportInfo) { - let expSrc = this.getExpSrc(node, src); - exports[expSrc] = exports[expSrc] || {}; - exports[expSrc] = {...exports[expSrc], ...exportInfo}; - } - }, - - // 退出节点 - exit(path) { - let {node} = path; - if (node._scope) { - scope = scope.parent; - } + Program: { + enter: (path) => { + topScope = path.scope; + }, }, + ...exportVisitor, + ...importVisitor, }); // console.log(src); @@ -296,7 +275,7 @@ class Graph { * exports: { * [本文件路径]: { * // export function(){} - * [name]: FunctionDeclaration|VariableDeclaration|ClassDeclaration + * // [name]: FunctionDeclaration|VariableDeclaration|ClassDeclaration * // export default function(){} | export default{} | export {a as default} | export default a * default: ExportDefaultDeclaration | FunctionDeclaration | ClassDeclaration |ExportSpecifier, * // export {a as aaa,b,c} @@ -331,11 +310,31 @@ class Graph { imports, exports, children: [], - scope, + topScope, isRoot, transformCommonJs, }; + // const generate = require('@babel/generator').default; + // const {writeFile} = require('./util'); + // let path = require('path'); + // const {code: outputCode} = generate( + // ast, + // { + // /* options */ + // decoratorsBeforeExport: true, + // }, + // code + // ); + // writeFile( + // path.resolve( + // path.dirname(src), + // './shaking', + // path.basename(src) + // ), + // outputCode + // ); + analyzedFile[src] = dep; Object.keys(dep.imports).forEach((childSrc, index) => { diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index 8c676a7b..54bff025 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -1,6 +1,6 @@ const traverse = require('@babel/traverse').default; const generate = require('@babel/generator').default; -const {writeFile} = require('./util'); +const {writeFile, dceDeclaration} = require('./util'); let {Graph} = require('./graph'); @@ -66,6 +66,34 @@ function collectReferences(dep) { dep.children.forEach((child) => collectReferences(child)); } +// 判断两个path是否互相包含 +function checkTwoPathContainMutually(pathA, pathB) { + let is = false; + + let doCheck = (_pathA, _pathB) => { + traverse( + _pathA.node, + { + enter(path) { + if (path === _pathB) { + is = true; + path.stop(); + } + }, + }, + _pathA.scope + ); + }; + + doCheck(pathA, pathB); + + if (!is) { + doCheck(pathB, pathA); + } + + return is; +} + const REQUIRE_TO_IMPORT_DEFAULT = 'require_to_import_default'; /** * export node 有一个_shake标志,如果该export没有被import,或者被import后没有使用,_shake = 1 @@ -78,7 +106,7 @@ function shake(dep) { return; } - let imports = dep.imports; + let {imports, exports, isRoot} = dep; let mark = (dep, usedNames, childSrc) => { if (usedNames.length) { @@ -95,13 +123,13 @@ function shake(dep) { } let usedExports = {}; - let addUsedExport = (src, node) => { + let addUsedExport = (src, path) => { usedExports[src] = usedExports[src] || {}; - let local = node.local; + let local = path.node.local; if (local) { - usedExports[src][local.name] = node; + usedExports[src][local.name] = path; } else { - usedExports[src]['*'] = node; + usedExports[src]['*'] = path; } }; @@ -116,29 +144,29 @@ function shake(dep) { ); let markedDefalut = false; if (localExports) { - Object.entries(localExports[1]).forEach(([name, node]) => { + Object.entries(localExports[1]).forEach(([name, path]) => { if (name === 'default') { if (hasDefalut) { - node._shake = 0; + path._shake = 0; markedDefalut = true; } } else { - node._shake = 0; + path._shake = 0; } }); } externalExports.forEach(([src, value]) => { - Object.entries(value).forEach(([name, node]) => { + Object.entries(value).forEach(([name, path]) => { if ( (name === 'default' && hasDefalut && !markedDefalut) || name !== 'default' ) { - if (node._shake === 1) { - node._shake = 0; - addUsedExport(src, node); + if (path._shake === 1) { + path._shake = 0; + addUsedExport(src, path); } } }); @@ -146,30 +174,19 @@ function shake(dep) { } else { usedNames.forEach((name) => { if (localExports) { - // if (name === REQUIRE_TO_IMPORT_DEFAULT) { - // Object.values(localExports[1]).forEach((node) => { - // // exports 转换的 export 节点 - // if (node.$t_cjs_temp_export) { - // node._shake = 0; - // } - // }); - - // return; - // } - - let node = localExports[1][name]; - if (node) { - node._shake = 0; + let path = localExports[1][name]; + if (path) { + path._shake = 0; return; } } externalExports.forEach(([src, value]) => { - let node = value[name] || value['*']; - if (node) { - if (node._shake === 1) { - node._shake = 0; - addUsedExport(src, node); + let path = value[name] || value['*']; + if (path) { + if (path._shake === 1) { + path._shake = 0; + addUsedExport(src, path); } } }); @@ -185,15 +202,15 @@ function shake(dep) { Object.entries(imports).forEach(([src, value]) => { let usedNames = []; - Object.entries(value).forEach(([name, node]) => { + Object.entries(value).forEach(([name, path]) => { // require 转成的 import default 节点 // 这些节点默认被本文件使用 - if (node.$t_cjs_temp_default_import) { + if (path.node.$t_cjs_temp_default_import) { usedNames.push(REQUIRE_TO_IMPORT_DEFAULT); return; } - if (node === 'child_scope_require') { + if (path.node === 'child_scope_require') { if (name === 'default') { usedNames.push(REQUIRE_TO_IMPORT_DEFAULT); } else { @@ -203,13 +220,25 @@ function shake(dep) { return; } - if (node._usedByNodes && node._usedByNodes.length) { - usedNames.push(name); - } + usedNames.push(name); }); mark(dep, usedNames, src); }); + // 根节点的export语句默认全部保留 + // 所以还需要处理根节点的export语句(export {} from '') + if (isRoot) { + Object.entries(exports).forEach(([src, value]) => { + if (src !== dep.src) { + let usedNames = []; + Object.entries(value).forEach(([name]) => { + usedNames.push(name); + }); + mark(dep, usedNames, src); + } + }); + } + dep._shook = true; dep.children.forEach((child) => shake(child)); @@ -220,47 +249,9 @@ function remove(dep) { return; } - let {scope, exports} = dep; - let loop = true; - - let markRemoved = (node) => { - node._removed = 1; - traverse(node, { - noScope: true, - enter(path) { - let {node} = path; - node._removed = 1; - }, - }); - }; - - let doRemove = (scope) => { - let {nodes: allNodes} = scope; - Object.values(allNodes).forEach((nodes) => { - nodes.forEach((node) => { - if (node._removed === 1) { - return; - } - - if ( - (node._usedByNodes.length === 0 && - (node._shake === 1 || node._shake === undefined)) || - (node._usedByNodes.length !== 0 && - node._usedByNodes.every((node) => node._removed)) - ) { - loop = true; - markRemoved(node); - } - }); - }); - - scope.children.forEach((childScope) => { - doRemove(childScope); - }); - }; + let {topScope, exports, src} = dep; let transformCommonJs = dep.transformCommonJs; - transformCommonJs.traverseTransformedModuleDeclaration(markRemoved); /** * 遍历exports,shake 标志表示该节点是否被外部有效的 import(即import的方法变量被使用过) @@ -271,38 +262,31 @@ function remove(dep) { * shake=1且_usedByNodes不存在,表示该export节点即不被外部有效import,也不会被内部使用 * shake=1且_usedByNodes存在且有值,表示该节点不被外部有效import,但被内部使用 */ + Object.entries(exports).forEach(([src, value]) => { - Object.entries(value).forEach(([name, node]) => { - if (node.$t_cjs_temp_export) { + Object.entries(value).forEach(([name, path]) => { + if (path.node.$t_cjs_temp_export) { if ( !transformCommonJs.state.isDynamicUsedExportsProperty && - node._shake === 1 && + path._shake === 1 && !transformCommonJs.state.usedExports.has(name) ) { - let cjsExportNode = transformCommonJs.getCJSExport(node); - if (cjsExportNode) { - console.log('111'); - markRemoved(cjsExportNode); - } + transformCommonJs.deleteCJSExport(path); } return; } - if ( - node._shake === 1 && - (!node._usedByNodes || - (node._usedByNodes && node._usedByNodes.length === 0)) - ) { - markRemoved(node); + if (path._shake === 1) { + path.remove(); } }); }); - while (loop) { - loop = false; - doRemove(scope); - } + transformCommonJs.deleteTransformedModuleDeclaration(); + + + dceDeclaration(topScope, true); dep._removed = true; @@ -319,21 +303,6 @@ function output(dep) { return; } - console.log(src); - if (src.endsWith('cjs1.js')) { - console.log('ss'); - } - - traverse(ast, { - enter(path) { - let {node} = path; - // console.log(path.toString()); - if (node._removed === 1) { - path.remove(); - } - }, - }); - const {code: outputCode} = generate( ast, { @@ -365,11 +334,11 @@ function output(dep) { function start(entries) { let graph = new Graph(entries); - graph.roots.forEach((root) => { - collectReferences(root); - }); + // graph.roots.forEach((root) => { + // collectReferences(root); + // }); - console.log('collected'); + // console.log('collected'); graph.roots.forEach((root) => { shake(root); diff --git a/packages/wxa-cli/src/tree-shake/tansform-commonJS.js b/packages/wxa-cli/src/tree-shake/tansform-commonJS.js index 056807af..f3708ac5 100644 --- a/packages/wxa-cli/src/tree-shake/tansform-commonJS.js +++ b/packages/wxa-cli/src/tree-shake/tansform-commonJS.js @@ -96,10 +96,10 @@ class TransformCommonJs { }); } - deleteCJSExport(esmExportNode) { + deleteCJSExport(esmExportPath) { Array.from(this.state.globalESMExports).some( ([exportPath, cjsPaths]) => { - if (this.isChildNode(exportPath.node, esmExportNode)) { + if (this.isChildNode(exportPath.node, esmExportPath.node)) { cjsPaths.forEach((p) => p.remove()); return true; } @@ -107,21 +107,6 @@ class TransformCommonJs { ); } - getCJSExport(esmExportNode) { - let node = null; - - Array.from(this.state.globalESMExports).some( - ([exportPath, cjsPaths]) => { - if (this.isChildNode(exportPath.node, esmExportNode)) { - node = cjsPaths[0].node; - return true; - } - } - ); - - return node; - } - markNodeDeep(node, flag) { node[flag] = true; traverse(node, { @@ -203,16 +188,16 @@ class TransformCommonJs { let globalESMImports = new Map(); this.state.globalESMImports.forEach((paths, node) => { - this.markNodeDeep(node, '$t_cjs_temp_import'); let importPath = path.unshiftContainer('body', node)[0]; + this.markNodeDeep(node, '$t_cjs_temp_import'); globalESMImports.set(importPath, paths); }); this.state.globalESMImports = globalESMImports; let globalESMExports = new Map(); this.state.globalESMExports.forEach((paths, node) => { - this.markNodeDeep(node, '$t_cjs_temp_export'); let exportPath = path.pushContainer('body', node)[0]; + this.markNodeDeep(node, '$t_cjs_temp_export'); globalESMExports.set(exportPath, paths); }); this.state.globalESMExports = globalESMExports; @@ -395,6 +380,7 @@ class TransformCommonJs { ]); let declarationPath = path.insertBefore(declaration)[0]; + path.scope.registerBinding('let', declarationPath); let rightPath = path.get('right'); rightPath.replaceWith(id); diff --git a/packages/wxa-cli/src/tree-shake/util.js b/packages/wxa-cli/src/tree-shake/util.js index c55305d9..52dadc2b 100644 --- a/packages/wxa-cli/src/tree-shake/util.js +++ b/packages/wxa-cli/src/tree-shake/util.js @@ -2,6 +2,7 @@ let fs = require('fs'); let path = require('path'); let mkdirp = require('mkdirp'); const {parse} = require('@babel/parser'); +const t = require('@babel/types'); let findRoot = require('find-root'); function readFile(p) { @@ -145,6 +146,54 @@ function parseESCode(code, plugins = [], options) { }); } +function dceDeclaration(scope, trackReferences = false) { + let hasRemoved = false; + Object.entries(scope.bindings).forEach(([name, binding]) => { + // 类似于let a = function ff(){} + // ff 是函数内部作用域的binding,ff不应该被删除 + if (t.isFunctionExpression(binding.path)) { + return; + } + + if (!binding.referenced) { + scope.removeOwnBinding(name); + binding.path.remove(); + hasRemoved = true; + return; + } + + // 使用path.remove删除节点后 + // 并不会让 scope 中的 binding.referenced 等信息更新 + // 即使重新遍历也不会更新 + if (trackReferences) { + let canRemove = binding.referencePaths.every((reference) => { + let parentPath = reference; + while (parentPath) { + if (!parentPath.node) { + return true; + } + + parentPath = parentPath.parentPath; + } + + return false; + }); + + if (canRemove) { + scope.removeOwnBinding(name); + binding.path.remove(); + hasRemoved = true; + } + } + }); + + // 处理声明之间循环引用 + // 当一个声明未被使用时,那该声明所引用的其他声明不算真正使用 + if (hasRemoved) { + dceDeclaration(scope, true); + } +} + // console.log( // resolveDepSrc({ // fileSrc: path.join(cwd, './src/a.js'), @@ -161,4 +210,5 @@ module.exports = { writeFile, resolveDepSrc, parseESCode, + dceDeclaration, }; From de2404a2e11bf5e0ea7eaa380eadc8154683d52a Mon Sep 17 00:00:00 2001 From: sparklinm Date: Sat, 10 Jul 2021 10:28:09 +0800 Subject: [PATCH 11/20] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=20commonjs=20s?= =?UTF-8?q?hake?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/example/index.js | 59 ++- packages/wxa-cli/example/shaking/cjs1.js | 15 +- packages/wxa-cli/example/shaking/cjs2.js | 6 +- packages/wxa-cli/example/shaking/index.js | 109 +++- packages/wxa-cli/example/shaking/user.js | 19 +- packages/wxa-cli/example/user.js | 8 +- packages/wxa-cli/src/tree-shake/config.js | 40 ++ packages/wxa-cli/src/tree-shake/graph.js | 126 +++-- packages/wxa-cli/src/tree-shake/index.js | 400 +++++++------- .../src/tree-shake/tansform-commonJS.js | 499 ++++++++---------- packages/wxa-cli/src/tree-shake/test.js | 25 + packages/wxa-cli/src/tree-shake/util.js | 173 ++++-- 12 files changed, 867 insertions(+), 612 deletions(-) create mode 100644 packages/wxa-cli/src/tree-shake/config.js create mode 100644 packages/wxa-cli/src/tree-shake/test.js diff --git a/packages/wxa-cli/example/index.js b/packages/wxa-cli/example/index.js index ad6a6836..abf3bdb1 100644 --- a/packages/wxa-cli/example/index.js +++ b/packages/wxa-cli/example/index.js @@ -1,5 +1,5 @@ /* eslint-disable one-var */ -import getMyUser, {getName as getMyName} from './user'; +import getAge, {getName as getMyName} from './user'; import * as user from './user'; import {getName as tttqw} from './user'; @@ -12,7 +12,9 @@ getName(); let ssqqww =1; -console.log(user); +// console.log(user); +console.log(getAge); + let a = {x: 1}, n = 1; let t = 10; @@ -27,6 +29,13 @@ function m(x = 1, y) { } m(); +try { + let a = 1; + console.log(a); +} catch (error) { + +} + let ttt = function({x: xxx, y}) {}; let sss = (a, b) => {}; @@ -41,7 +50,36 @@ class Myclass { [n] = () => {}; } -export function mm() {} +let [zz, xx, cc] = [1, 2, 3]; +let {x: x1} = {x: 1, y2: 2}; + +let {detail: {code, code1}} = {detail: {code: 1}}; + + +let o22=1; +let o11 = o22 =3; + +console.log(o22); + + +let clearErrorMsg = function({p1, p2}, {currentTarget: {dataset: {rule, as, name, opts={}}}}, [asq, ttqw], ppp) { + let asdf='p'; +}; + + +function aaa({p1, p2}) { + let asdwqe='p'; + + function att() { + + } +}; + +aaa(); + + +clearErrorMsg(); + mm(); @@ -52,6 +90,11 @@ function name(params) { t.q; } + +function aaas() { + name(); +} + let obj = { x: 1, t() {}, @@ -69,18 +112,20 @@ let obj = { export let qwe=1, rty=2; export function getName() {} +export function mm() {} + // export {m as qqqqq, a as default}; // export {x, y} from './a'; -// export default function asf() {}; +export default class asf {}; export {Myclass}; // eslint-disable-next-line no-var export {mm as ttttttt}; -export {getName as tttt} from './user'; -export {default} from './user'; +// export {getName as tttt} from './user'; +// export {default} from './user'; -export * as tttttt from './user'; +// export * as tttttt from './user'; diff --git a/packages/wxa-cli/example/shaking/cjs1.js b/packages/wxa-cli/example/shaking/cjs1.js index e14a0de4..7aac95b8 100644 --- a/packages/wxa-cli/example/shaking/cjs1.js +++ b/packages/wxa-cli/example/shaking/cjs1.js @@ -2,17 +2,18 @@ let fn1 = require('./cjs2').fn1; fn1(); Object.defineProperty(exports, '__esModule', { - value: true, + value: true }); exports.writeFile = writeFile; exports.isFile = isFile; module.exports = { - getFiles, + getFiles }; -function getFiles() { +function getFiles(dir = process.cwd(), prefix = '') { let rst = []; - exports.rst = rst; // exports[aaaa] = aaaa; + exports.rst = rst; + let aaaa = 'aaa'; // exports[aaaa] = aaaa; // let ttt= require('sss'); // console.log(ttt); // exports.addClass; @@ -25,6 +26,8 @@ function getFiles() { // } -function writeFile() {} +function writeFile(p, data) {} -function isFile() {} +function isFile(p) {} + +let _m = function m() {}; \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/cjs2.js b/packages/wxa-cli/example/shaking/cjs2.js index 3e913ad3..faf6661a 100644 --- a/packages/wxa-cli/example/shaking/cjs2.js +++ b/packages/wxa-cli/example/shaking/cjs2.js @@ -1,3 +1,5 @@ -function fn1() {} +function fn1(params) {} -exports.fn1 = fn1; \ No newline at end of file +exports.fn1 = fn1; + +let _fn = function fn4() {}; \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/index.js b/packages/wxa-cli/example/shaking/index.js index b01cb479..327a1ba9 100644 --- a/packages/wxa-cli/example/shaking/index.js +++ b/packages/wxa-cli/example/shaking/index.js @@ -1,29 +1,45 @@ /* eslint-disable one-var */ +import getAge from './user'; import './user'; -import * as user from './user'; import './user'; -import {writeFile, isFile} from './cjs1'; +import { writeFile, isFile } from './cjs1'; writeFile(); isFile(); getName(); -console.log(user); +let ssqqww = 1; // console.log(user); + +console.log(getAge); let a = { - x: 1, + x: 1 }, n = 1; let t = 10; -function m() { +function m(x = 1, y) { a = 5; ++a; t = 9; t + 5; + let qqq = 10; let ssqqww = 5; console.log(ssqqww); } m(); -[1, 2, 3].forEach(function() {}); + +try { + let a = 1; + console.log(a); +} catch (error) {} + +let ttt = function ({ + x: xxx, + y +}) {}; + +let sss = (a, b) => {}; + +[1, 2, 3].forEach(function (item) {}); for (i = 0; i < 100; i++) {} @@ -32,12 +48,62 @@ class Myclass { [n] = () => {}; } -function mm() {} +let [zz, xx, cc] = [1, 2, 3]; +let { + x: x1 +} = { + x: 1, + y2: 2 +}; +let { + detail: { + code, + code1 + } +} = { + detail: { + code: 1 + } +}; +let o22 = 1; +let o11 = o22 = 3; +console.log(o22); -export {mm}; +let clearErrorMsg = function ({ + p1, + p2 +}, { + currentTarget: { + dataset: { + rule, + as, + name, + opts = {} + } + } +}, [asq, ttqw], ppp) { + let asdf = 'p'; +}; + +function aaa({ + p1, + p2 +}) { + let asdwqe = 'p'; +} + +; +aaa(); +clearErrorMsg(); mm(); +let obj = { + x: 1, + + t() {} -(function() {})(); // export default { +}; + +(function (x, y) {})(); // export default { // x: 1, // t() { // }, @@ -48,17 +114,22 @@ mm(); let qwe = 1, rty = 2; -export {qwe, rty}; +export { qwe, rty }; function getName() {} -export {getName}; -// export {m as qqqqq, a as default}; -// export {x, y} from './a'; -// export default function asf() {}; -export {Myclass}; // eslint-disable-next-line no-var +export { getName }; + +function mm() {} + +export { mm }; + +class asf {} + +export default asf; +; +export { Myclass }; // eslint-disable-next-line no-var -export {mm as ttttttt}; -export {getName as tttt} from './user'; -export {default} from './user'; -export * as tttttt from './user'; +export { mm as ttttttt }; // export {getName as tttt} from './user'; +// export {default} from './user'; +// export * as tttttt from './user'; \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/user.js b/packages/wxa-cli/example/shaking/user.js index 30abbdf1..58f0c873 100644 --- a/packages/wxa-cli/example/shaking/user.js +++ b/packages/wxa-cli/example/shaking/user.js @@ -1,16 +1,11 @@ -function getName() {} +export {}; -export {getName}; -// export default function getUser(params) { -// } -let a = 1; -export default a; // eslint-disable-next-line one-var +function getAge(params) {} -let mm1 = 1, - c = function mm2() {}; - -export {mm1, c}; +export default getAge; -function fn2() {} +let mm1 = 1, + c = function mm2(params) {}; -export {fn2}; +export {}; +export {}; \ No newline at end of file diff --git a/packages/wxa-cli/example/user.js b/packages/wxa-cli/example/user.js index 1a9d9326..cfcf9a94 100644 --- a/packages/wxa-cli/example/user.js +++ b/packages/wxa-cli/example/user.js @@ -2,12 +2,12 @@ export function getName() { } -// export default function getUser(params) { +export default function getAge(params) { -// } +} -let a =1; -export default a; +// let a =1; +// export default a; // eslint-disable-next-line one-var export let mm1 =1, c=function mm2(params) { diff --git a/packages/wxa-cli/src/tree-shake/config.js b/packages/wxa-cli/src/tree-shake/config.js new file mode 100644 index 00000000..5ed7e593 --- /dev/null +++ b/packages/wxa-cli/src/tree-shake/config.js @@ -0,0 +1,40 @@ +module.exports = { + entry: [ + { + // 路径 + src: '', + // 文件内容(可选) + content: '', + }, + ], + resolveSrc: { + // '/a/b/c',绝对路径根目录 + // 例如src, '/a/b/c' 转换为 /src/a/b/b + root: '', + // {'@': 'src'},路径别名 + alias: {}, + npm: 'node_modules', + }, + commonJS: { + enable: false, + // 无法追踪动态引入的模块 + // 如果有模块被动态引入,需要在这里设置该模块路径 + // 将跳过对该模块的 cjs 转 esm + dynamicRequireTargets: [], + // 设置 exports 上的哪些属性不会被转换为 esm + // 默认值有 '__esModule' + ingoreKeys: [], + }, + parseOptions: { + plugins: [ + ['decorators', {decoratorsBeforeExport: true}], + 'classProperties', + 'jsx', + 'typescript', + 'exportNamespaceFrom', + 'exportDefaultFrom', + 'objectRestSpread', + ], + sourceType: 'unambiguous', + }, +}; diff --git a/packages/wxa-cli/src/tree-shake/graph.js b/packages/wxa-cli/src/tree-shake/graph.js index fccae28b..7a7a09d3 100644 --- a/packages/wxa-cli/src/tree-shake/graph.js +++ b/packages/wxa-cli/src/tree-shake/graph.js @@ -1,11 +1,17 @@ const traverse = require('@babel/traverse').default; const t = require('@babel/types'); -const {readFile, resolveDepSrc, parseESCode, dceDeclaration} = require('./util'); +const { + readFile, + resolveDepSrc, + parseESCode, + dceDeclaration, +} = require('./util'); +let config = require('./config'); let {TransformCommonJs} = require('./tansform-commonJS'); class Graph { constructor(entries) { - this.entries = entries; + this.entries = config.entry; this.analysis(); } @@ -13,8 +19,7 @@ class Graph { let s = resolveDepSrc({ fileSrc, depSrc, - root: 'src', - alias: {'@': 'src'}, + ...config.resolveSrc, }); if (!s.endsWith('.js')) { @@ -41,6 +46,9 @@ class Graph { let store = (name, path, node) => { let impSrc = this.getAbsolutePath(src, node.source.value); imports[impSrc] = imports[impSrc] || {}; + if (name === '' || path === '') { + return; + } imports[impSrc][name] = path; }; @@ -49,26 +57,32 @@ class Graph { enter: (path) => { let {node} = path; let specifierPaths = path.get('specifiers'); - specifierPaths.forEach((specifierPath) => { - let specifierNode = specifierPath.node; - let name = - specifierNode.imported && - specifierNode.imported.name; - - if (!name) { - if ( - specifierNode.type === 'ImportDefaultSpecifier' - ) { - name = 'default'; - } else if ( - specifierNode.type === - 'ImportNamespaceSpecifier' - ) { - name = '*'; + if (specifierPaths && specifierPaths.length) { + specifierPaths.forEach((specifierPath) => { + let specifierNode = specifierPath.node; + let name = + specifierNode.imported && + specifierNode.imported.name; + + if (!name) { + if ( + specifierNode.type === + 'ImportDefaultSpecifier' + ) { + name = 'default'; + } else if ( + specifierNode.type === + 'ImportNamespaceSpecifier' + ) { + name = '*'; + } } - } - store(name, specifierPath, node); - }); + store(name, specifierPath, node); + }); + } else { + // import './a' + store('', '', node); + } }, }, }; @@ -81,9 +95,9 @@ class Graph { let store = (name, path, node) => { if (isRoot) { - path._shake = 0; + path.$extReferences = ['root']; } else { - path._shake = 1; + path.$extReferences = []; } let expSrc = this.getExpSrc(node, src); exports[expSrc] = exports[expSrc] || {}; @@ -126,7 +140,7 @@ class Graph { ); } - return {specifiers, declarationNode}; + return {specifiers, declarationPath}; }; let visitor = { @@ -137,10 +151,12 @@ class Graph { if (node.specifiers && node.specifiers.length) { storeSpecifiers(path, node); } else { - let {specifiers, declarationNode} = + let {specifiers, declarationPath} = transformExportDeclarationToSpecifiers(path); - path.insertBefore(declarationNode); + let newDeclarationPath = path.insertBefore( + declarationPath.node + )[0]; let exportNamedDeclaration = t.exportNamedDeclaration( null, specifiers @@ -148,7 +164,13 @@ class Graph { let newExportPath = path.insertAfter( exportNamedDeclaration )[0]; + // 删除声明节点会同时删除相应binding path.remove(); + // 注册binding + // 注册binding是根据path来注册 + // path.scope.registerBinding(declarationPath.node.kind || 'hoisted', newDeclarationPath); + // 注册binding,并不会自动更新相应binding的referencePaths等信息,调用crawl更新 + // path.scope.crawl(); storeSpecifiers(newExportPath, node); } @@ -162,19 +184,18 @@ class Graph { // TODO,未处理 export default a=1 这类表达式 // 类似于export default function mm(){} - // 单独声明mm,并export default {mm} + // 单独声明mm,并export default mm if (declarationNode.id && declarationNode.id.name) { - path.insertBefore(declarationNode); + let newDeclarationPath = + path.insertBefore(declarationNode)[0]; let exportDefaultNode = t.exportDefaultDeclaration( - t.objectExpression([ - t.objectProperty( - t.identifier(declarationNode.id.name), - t.identifier(declarationNode.id.name) - ), - ]) + t.identifier(declarationNode.id.name) ); exportPath = path.insertAfter(exportDefaultNode)[0]; path.remove(); + // 注册binding + // path.scope.registerBinding( declarationNode.kind || 'hoisted', newDeclarationPath); + // path.scope.crawl(); } store('default', exportPath, node); @@ -226,9 +247,8 @@ class Graph { if (analyzedFile[src]) { return analyzedFile[src]; } - - console.log('---'); - console.log(src); + + console.log('graph', src); let code = content || readFile(src); let ast = parseESCode(code); @@ -236,7 +256,9 @@ class Graph { this.dceDeclaration(ast); let topScope = null; + let transformCommonJs = new TransformCommonJs({src, code, ast}); + let {visitor: exportVisitor, exports} = this.collectExport( src, isRoot @@ -274,10 +296,8 @@ class Graph { * * exports: { * [本文件路径]: { - * // export function(){} - * // [name]: FunctionDeclaration|VariableDeclaration|ClassDeclaration * // export default function(){} | export default{} | export {a as default} | export default a - * default: ExportDefaultDeclaration | FunctionDeclaration | ClassDeclaration |ExportSpecifier, + * default: ExportDefaultDeclaration, * // export {a as aaa,b,c} * [name]: ExportSpecifier * }, @@ -292,17 +312,29 @@ class Graph { * } */ - transformCommonJs.state.childScopeRequires.forEach( + transformCommonJs.state.cjsRequireModules.forEach( (names, requireSrc) => { let abSrc = this.getAbsolutePath(src, requireSrc); - let info = Array.from(names).map((name) => ({ - name: 'child_scope_require', - })); + imports[abSrc] = imports[abSrc] || {}; - imports[abSrc] = {...imports[abSrc], ...info}; + Array.from(names).forEach((name) => { + if (name === 'default') { + imports[abSrc].default = 'custom_import_name'; + imports[abSrc]['*'] = 'custom_import_name'; + return; + } + + imports[abSrc][name] = 'custom_import_name'; + }); } ); + transformCommonJs.state.cjsExportModules.forEach((path, name) => { + exports[src] = imports[src] || {}; + exports[src][name] = path; + path.$isCjsExport = true; + }); + let dep = { src, code, diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index 54bff025..05a255b1 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -1,115 +1,51 @@ -const traverse = require('@babel/traverse').default; const generate = require('@babel/generator').default; const {writeFile, dceDeclaration} = require('./util'); +let config = require('./config'); let {Graph} = require('./graph'); -function collectReferences(dep) { - if (dep._collcted) { - return; - } - - let {ast, scope} = dep; - - let findScope = (node) => { - let defineScope = scope.findDefiningScope(node.name); - if (defineScope) { - defineScope.nodes[node.name].forEach((declarationNode) => { - // 该声明语句被哪些identifier节点使用过 - declarationNode._usedByNodes.push(node); - }); - } - }; - - let collect = () => { - traverse(ast, { - enter: (path) => { - let {node} = path; - - if (node._scope) { - scope = node._scope; - } - - // obj.x 类型的属性访问,不算对x变量的使用 - if (node.type === 'MemberExpression') { - !node.computed && path.skipKey('property'); - } else if (node.type === 'ObjectProperty') { - // {x:1} 对象属性 - !node.computed && path.skipKey('key'); - } else if ( - [ - 'ClassMethod', - 'ClassPrivateMethod', - 'ClassProperty', - 'ClassDeclaration', - ].includes(node.type) - ) { - !node.computed && path.skipKey('key'); - } else if (node.type === 'Identifier') { - // TODO,怎么才算变量已经使用 - !node._skip && findScope(node); - } - }, - // 退出节点 - exit(path) { - let {node} = path; - if (node._scope) { - scope = scope.parent; - } - }, - }); - }; - - collect(); - dep._collcted = true; - - dep.children.forEach((child) => collectReferences(child)); -} - -// 判断两个path是否互相包含 -function checkTwoPathContainMutually(pathA, pathB) { - let is = false; - - let doCheck = (_pathA, _pathB) => { - traverse( - _pathA.node, - { - enter(path) { - if (path === _pathB) { - is = true; - path.stop(); - } - }, - }, - _pathA.scope - ); - }; - - doCheck(pathA, pathB); - - if (!is) { - doCheck(pathB, pathA); - } - - return is; -} - -const REQUIRE_TO_IMPORT_DEFAULT = 'require_to_import_default'; /** * export node 有一个_shake标志,如果该export没有被import,或者被import后没有使用,_shake = 1 * 在这里,遍历全局文件树,根据import和export关系,对没使用的export进行标记 * 但如果用require去引入一个export函数变量,这里并不能分析到这个export函数变量被使用过(所以不能去 require 一个 export) */ +let chain = {}; + function shake(dep) { if (dep._shook) { return; } - let {imports, exports, isRoot} = dep; + let {imports, exports, isRoot, src: depSrc} = dep; + + console.log('---'); + console.log('shake src', depSrc); + + let fileExportChain = []; + chain[depSrc] = fileExportChain; + let nameInExport = new Map(); + + // let markExport = (fileExportChain) => { + // Object.values(fileExportChain).forEach(([name, chainInfo]) => {}); + // }; + + let collectExportChain = (dep, childSrc, currentChain) => { + if (currentChain.length) { + let nextChain = []; + + let setCurrentChain = (chainNode, childName, path) => { + let childChainNode = { + name: childName, + path, + children: [], + parent: chainNode, + }; + chainNode.children.push(childChainNode); + nextChain.push(childChainNode); + path.$chain + }; - let mark = (dep, usedNames, childSrc) => { - if (usedNames.length) { let child = dep.children.find((child) => child.src === childSrc); let exportsArray = Object.entries(child.exports); let localIndex = exportsArray.findIndex( @@ -123,121 +59,173 @@ function shake(dep) { } let usedExports = {}; - let addUsedExport = (src, path) => { - usedExports[src] = usedExports[src] || {}; + + let getExportLocalName = (path) => { let local = path.node.local; if (local) { - usedExports[src][local.name] = path; + return local.name; + } + + return '*'; + }; + + let addUsedExport = (src, name, path) => { + usedExports[src] = usedExports[src] || {}; + + if (name) { + usedExports[src][name] = path; + } + }; + + let collect = (chainNode, path, src, defaultLocalName) => { + let localName = ''; + let name = chainNode.name; + + if (defaultLocalName) { + localName = defaultLocalName; + } else { + localName = getExportLocalName(path); + } + + let names = nameInExport.get(path); + + if (names && names.has(localName)) { + return; + } + + if (names) { + names.add(localName); } else { - usedExports[src]['*'] = path; + names = new Set(); + names.add(localName); } + + setCurrentChain(chainNode, localName, path); + addUsedExport(src, localName, path); }; - let hasAll = usedNames.some( - (name) => name === '*' || name === REQUIRE_TO_IMPORT_DEFAULT + let importAllChainNode = currentChain.find( + (node) => node.name === '*' ); - if (hasAll) { - let hasDefalut = usedNames.some( - (name) => - name === 'default' || name === REQUIRE_TO_IMPORT_DEFAULT + if (importAllChainNode) { + let importDefaultChainNode = currentChain.find( + (node) => node.name === 'default' ); + let markedDefalut = false; if (localExports) { Object.entries(localExports[1]).forEach(([name, path]) => { if (name === 'default') { - if (hasDefalut) { - path._shake = 0; + if (importDefaultChainNode) { markedDefalut = true; + setCurrentChain( + importDefaultChainNode, + 'dafault', + path + ); } } else { - path._shake = 0; + let localName = getExportLocalName(path); + setCurrentChain( + importAllChainNode, + localName, + path + ); } }); } - externalExports.forEach(([src, value]) => { - Object.entries(value).forEach(([name, path]) => { + externalExports.forEach(([src, exportInfo]) => { + Object.entries(exportInfo).forEach(([name, path]) => { if ( - (name === 'default' && - hasDefalut && - !markedDefalut) || - name !== 'default' + name === 'default' && + importDefaultChainNode && + !markedDefalut ) { - if (path._shake === 1) { - path._shake = 0; - addUsedExport(src, path); - } + collect(importDefaultChainNode, path, src); + } else if (name !== 'default') { + collect(importAllChainNode, path, src); } }); }); } else { - usedNames.forEach((name) => { + currentChain.forEach((chainNode) => { + let name = chainNode.name; if (localExports) { let path = localExports[1][name]; + if (path) { - path._shake = 0; + if (name === 'default') { + setCurrentChain(chainNode, 'dafault', path); + } else { + let localName = getExportLocalName(path); + setCurrentChain(chainNode, localName, path); + } return; } } - externalExports.forEach(([src, value]) => { - let path = value[name] || value['*']; + externalExports.forEach(([src, exportInfo]) => { + let path = exportInfo[name]; + if (path) { - if (path._shake === 1) { - path._shake = 0; - addUsedExport(src, path); - } + collect(chainNode, path, src); + } + + path = exportInfo['*']; + + if (path) { + collect(chainNode, path, src, name); } }); }); } Object.entries(usedExports).forEach((src, value) => { - mark(child, Object.keys(value), src); + let childUsedNames = Object.keys(value); + let childChain = childUsedNames.map((n) => { + return nextChain.find((chainNode) =>chainNode.name === n); + }); + + collectExportChain(child, src, childChain); }); } }; + // if (depSrc.endsWith('ZY\\models\\index.js')) { + // console.log('ssssss'); + // } + Object.entries(imports).forEach(([src, value]) => { let usedNames = []; Object.entries(value).forEach(([name, path]) => { - // require 转成的 import default 节点 - // 这些节点默认被本文件使用 - if (path.node.$t_cjs_temp_default_import) { - usedNames.push(REQUIRE_TO_IMPORT_DEFAULT); - return; - } - - if (path.node === 'child_scope_require') { - if (name === 'default') { - usedNames.push(REQUIRE_TO_IMPORT_DEFAULT); - } else { - usedNames.push(name); - } - - return; - } - usedNames.push(name); + fileExportChain.push({ + parent: null, + name, + path, + children: [], + }); }); - mark(dep, usedNames, src); + + collectExportChain(dep, src, fileExportChain); }); // 根节点的export语句默认全部保留 // 所以还需要处理根节点的export语句(export {} from '') - if (isRoot) { - Object.entries(exports).forEach(([src, value]) => { - if (src !== dep.src) { - let usedNames = []; - Object.entries(value).forEach(([name]) => { - usedNames.push(name); - }); - mark(dep, usedNames, src); - } - }); - } + // if (isRoot) { + // Object.entries(exports).forEach(([src, exportInfo]) => { + // if (src !== dep.src) { + // let usedNames = []; + // Object.entries(exportInfo).forEach(([name]) => { + // usedNames.push(name); + // }); + // collectExportChain(dep, usedNames, src); + // } + // }); + // } dep._shook = true; @@ -253,6 +241,12 @@ function remove(dep) { let transformCommonJs = dep.transformCommonJs; + console.log('remove', src); + + // if (src.endsWith('ZY\\models\\applyCenter.model.js')) { + // console.log('ss'); + // } + /** * 遍历exports,shake 标志表示该节点是否被外部有效的 import(即import的方法变量被使用过) * 如果shake=1,表示没有被有效import过 @@ -265,28 +259,16 @@ function remove(dep) { Object.entries(exports).forEach(([src, value]) => { Object.entries(value).forEach(([name, path]) => { - if (path.node.$t_cjs_temp_export) { - if ( - !transformCommonJs.state.isDynamicUsedExportsProperty && - path._shake === 1 && - !transformCommonJs.state.usedExports.has(name) - ) { - transformCommonJs.deleteCJSExport(path); - } - - return; - } - if (path._shake === 1) { + if (path.$isCjsExport) { + transformCommonJs.deleteCJSExport(name); + } path.remove(); } }); }); - transformCommonJs.deleteTransformedModuleDeclaration(); - - - dceDeclaration(topScope, true); + dceDeclaration(topScope); dep._removed = true; @@ -331,14 +313,47 @@ function output(dep) { return contents; } -function start(entries) { - let graph = new Graph(entries); +function setConfig(options) { + if ( + !options.entry || + !Array.isArray(options.entry) || + !options.entry.length + ) { + throw new Error('Options entry is required'); + } + + config.entry = options.entry; + + if (options.resolveSrc) { + Object.assign(config.resolveSrc, options.resolveSrc); + } + + if (options.commonJS) { + Object.assign(config.commonJS, options.commonJS); + config.commonJS.ingoreKeys.push('__esModule'); + } + + if (options.parseOptions) { + if (options.parseOptions.plugins) { + config.parseOptions.plugins = [ + ...config.parseOptions.plugins, + ...options.parseOptions.plugins, + ]; - // graph.roots.forEach((root) => { - // collectReferences(root); - // }); + delete options.parseOptions.plugins; + } + + config.parseOptions = { + ...config.parseOptions, + ...options.parseOptions, + }; + } +} - // console.log('collected'); +function treeShake(options = {}) { + setConfig(options); + + let graph = new Graph(); graph.roots.forEach((root) => { shake(root); @@ -356,13 +371,13 @@ function start(entries) { } module.exports = { - start, + treeShake, }; console.time('end'); let path = require('path'); let entrySrc = path.resolve(__dirname, '../../example/index.js'); -start([{src: entrySrc}]); +treeShake([{src: entrySrc}]); console.timeEnd('end'); // function name(params) { @@ -370,28 +385,15 @@ console.timeEnd('end'); // } // name(); - -// let code = `function scopeOnce() { -// var ref = "This is a binding"; -// var xx = 'binding2' - -// if(xx){ -// let oo="binding3" -// } - -// ref + '1'; // This is a reference to a binding - -// function scopeTwo() { -// ref+'2'; // This is a reference to a binding from a lower scope -// } -// }`; +// const generate = require('@babel/generator').default; +// const traverse = require('@babel/traverse').default; +// const {parse} = require('@babel/parser'); +// let code = `exports.x=1;let t =exports`; // let ast = parse(code, {sourceType: 'unambiguous'}); // traverse(ast, { // enter(path) { -// let {node} =path; -// if (node.type === 'VariableDeclarator') { -// console.log(path.scope); -// } +// console.log(path.scope) + // }, // }); diff --git a/packages/wxa-cli/src/tree-shake/tansform-commonJS.js b/packages/wxa-cli/src/tree-shake/tansform-commonJS.js index f3708ac5..b530ca53 100644 --- a/packages/wxa-cli/src/tree-shake/tansform-commonJS.js +++ b/packages/wxa-cli/src/tree-shake/tansform-commonJS.js @@ -1,9 +1,16 @@ +let path = require('path'); + const traverse = require('@babel/traverse').default; const generate = require('@babel/generator').default; -let {check} = require('reserved-words'); -const {readFile, writeFile, parseESCode} = require('./util'); +const { + readFile, + writeFile, + parseESCode, + isChildNode, + unique, +} = require('./util'); let t = require('@babel/types'); -let path = require('path'); +const config = require('./config'); let options = {}; @@ -20,7 +27,8 @@ function getStaticValue(node) { return false; } -function getStaticMemberProValue(node) { +// node: MemberExpression +function getStaticMemberPro(node) { if (node.computed) { return getStaticValue(node.property); } @@ -30,16 +38,22 @@ function getStaticMemberProValue(node) { class TransformCommonJs { state = { - globalESMImports: new Map(), - globalESMExports: new Map(), + // { + // moduleName: exports Path + // } + cjsExportModules: new Map(), + // { + // src: [moduleName] + // } + cjsRequireModules: new Map(), renamed: new Map(), identifiers: new Set(), isCJS: false, isESM: false, - childScopeRequires: new Map(), deletedNodes: new Map(), usedExports: new Set(), isDynamicUsedExportsProperty: false, + isUsedExportsObject: false, }; constructor({src, code, ast}) { @@ -47,23 +61,24 @@ class TransformCommonJs { this.code = code; this.ast = ast || parseESCode(code); - let dynamicRequireTargets = options.dynamicRequireTargets || []; + let dynamicRequireTargets = config.commonJS.dynamicRequireTargets || []; // 如果一个模块被其他模块动态导入 // 不对这个模块做任何处理 - if (dynamicRequireTargets.includes(src)) { + if (dynamicRequireTargets.includes(src) || !config.commonJS.enable) { return {src, code}; } + this.ingorekeys = config.commonJS.ingoreKeys; + this.transform(this.ast, options); - console.log('childScopeRequires', this.state.childScopeRequires); + console.log('cjsRequireModules', this.state.cjsRequireModules); console.log('usedExports', this.state.usedExports); console.log( 'isDynamicUsedExportsProperty', this.state.isDynamicUsedExportsProperty ); - - // this.deleteTransformedModuleDeclaration(); + console.log('isUsedExportsObject', this.state.isUsedExportsObject); } reset() { @@ -76,35 +91,21 @@ class TransformCommonJs { }); } - deleteTransformedModuleDeclaration() { - this.state.globalESMImports.forEach((paths, importPath) => { - importPath.remove(); - }); - - this.state.globalESMExports.forEach((paths, exportPath) => { - exportPath.remove(); - }); - } - - traverseTransformedModuleDeclaration(cb) { - this.state.globalESMImports.forEach((paths, importPath) => { - cb(importPath.node); - }); - - this.state.globalESMExports.forEach((paths, exportPath) => { - cb(exportPath.node); - }); - } + deleteCJSExport(exportName) { + if ( + this.state.isDynamicUsedExportsProperty || + this.state.usedExports.has(name) || + this.state.isUsedExportsObject + ) { + return; + } - deleteCJSExport(esmExportPath) { - Array.from(this.state.globalESMExports).some( - ([exportPath, cjsPaths]) => { - if (this.isChildNode(exportPath.node, esmExportPath.node)) { - cjsPaths.forEach((p) => p.remove()); - return true; - } + Array.from(this.state.cjsExportModules).some(([name, cjsPath]) => { + if (exportName === name) { + cjsPath.remove(); + return true; } - ); + }); } markNodeDeep(node, flag) { @@ -118,219 +119,116 @@ class TransformCommonJs { }); } - isChildNode(parent, child) { - if (parent === child) { - return true; - } - - let is = false; - - traverse(parent, { - noScope: true, - enter(path) { - let {node} = path; - if (node === child) { - is = true; - path.stop(); - } - }, - }); - - return is; - } - transform(ast, options = {}) { + let that = this; traverse(ast, { - Program: { - exit: (path) => { - // let allDeletePaths = []; - - // this.state.globalESMImports.forEach((paths) => { - // allDeletePaths = allDeletePaths.concat(paths); - // }); - - // this.state.globalESMExports.forEach((paths) => { - // allDeletePaths = allDeletePaths.concat(paths); - // }); - - // allDeletePaths.forEach((path) => { - // let allNextSiblingPaths = path.getAllNextSiblings(); - - // if (!allNextSiblingPaths.length) { - // this.state.deletedNodes.set( - // path.node, - // path.parentPath - // ); - // path.remove(); - // return; - // } - - // for (let i = 0; i < allNextSiblingPaths.length; i++) { - // let nextPath = allNextSiblingPaths[i]; - // let last = i === allNextSiblingPaths.length - 1; - // let find = - // !allDeletePaths.includes(nextPath) || last; - - // if (last) { - // nextPath = path.parentPath; - // } - - // if (find) { - // this.state.deletedNodes.set( - // path.node, - // nextPath - // ); - // path.remove(); - // break; - // } - // } - // }); - - let globalESMImports = new Map(); - this.state.globalESMImports.forEach((paths, node) => { - let importPath = path.unshiftContainer('body', node)[0]; - this.markNodeDeep(node, '$t_cjs_temp_import'); - globalESMImports.set(importPath, paths); - }); - this.state.globalESMImports = globalESMImports; - - let globalESMExports = new Map(); - this.state.globalESMExports.forEach((paths, node) => { - let exportPath = path.pushContainer('body', node)[0]; - this.markNodeDeep(node, '$t_cjs_temp_export'); - globalESMExports.set(exportPath, paths); - }); - this.state.globalESMExports = globalESMExports; - }, - }, CallExpression: { enter: (path) => { const {node} = path; - // Look for `require()` any renaming is assumed to be intentionally - // done to break state kind of check, so we won't look for aliases. + if ( t.isIdentifier(node.callee) && node.callee.name === 'require' ) { - // Require must be global for us to consider this a CommonJS - // module. this.state.isCJS = true; - // Normalize the string value, default to the standard string - // literal format of `{ value: "" }`. let source = getStaticValue(node.arguments[0]); if (source === false) { console.warn( - `Dynamic requires are not currently supported: ${path.toString()}. please configure dynamicrequiretargets` + `Dynamic cjsRequireModules are not currently supported: ${path.toString()}. please configure dynamicrequiretargets` ); return; } - const specifiers = []; let {parentPath} = path; let {node: parentNode} = parentPath; - let childScopeRequireNames = null; - - if (!t.isProgram(path.scope.path)) { - childScopeRequireNames = - this.state.childScopeRequires.get(source); - if (!childScopeRequireNames) { - childScopeRequireNames = new Set(); - this.state.childScopeRequires.set( - source, - childScopeRequireNames - ); - } + let requireNames = + this.state.cjsRequireModules.get(source); + if (!requireNames) { + requireNames = new Set(); + this.state.cjsRequireModules.set( + source, + requireNames + ); } - // Convert to named import. // let {a} = require('a') - if (t.isObjectPattern(parentNode.id)) { - if (childScopeRequireNames) { - parentNode.id.properties.forEach((prop) => { - childScopeRequireNames.add(prop.key); - }); - return; - } - - parentNode.id.properties.forEach((prop) => { - specifiers.push( - t.importSpecifier( - t.identifier(prop.value), - t.identifier(prop.key) - ) - ); - }); + let objectPatternPath = path.findParent((parent) => { + return t.isObjectPattern(parent.node.id); + }); + + if (objectPatternPath) { + objectPatternPath.node.properties.forEach( + (prop) => { + requireNames.add(prop.key); + } + ); } else if (t.isMemberExpression(parentNode)) { + // require('a').a + let name = getStaticMemberPro(parentNode); + // let a = require('a')[a],属于动态导入 - if (parentNode.computed) { + if (name === false) { console.warn( - `Dynamic requires are not currently supported: ${path.toString()}. please configure dynamicrequiretargets` + `Dynamic cjsRequireModules are not currently supported: ${path.toString()}. please configure dynamicrequiretargets` ); return; } - if (childScopeRequireNames) { - childScopeRequireNames.add( - parentNode.property.key - ); - return; - } - - specifiers.push( - t.importSpecifier( - t.identifier(parentNode.property.name), - t.identifier(parentNode.property.name) - ) - ); + requireNames.add(name); } else if (source) { - // Convert to default import. - if (childScopeRequireNames) { - childScopeRequireNames.add('default'); - return; - } - + // require('./a') + // 声明语句才有:let a = require('./a') let declaratorParentPath = path.find((path) => { return t.isVariableDeclarator(path); }); - let name = - (declaratorParentPath.node.id && + (declaratorParentPath && + declaratorParentPath.node.id && declaratorParentPath.node.id.name) || ''; - let id = name - ? t.identifier(name) - : path.scope.generateUidIdentifier(); - - // 由 require 转换的 import default 节点 - // 标记 - // 当 tree shake 时,对于这类节点: - // 1. 这类节点默认在本文件使用 - // 2. 当找到依赖文件时,依赖文件的 $t_cjs_temp_export(exports 转换的 export 节点)节点默认全部被有效 import - let defaultImportNode = - t.importDefaultSpecifier(id); - - this.markNodeDeep( - defaultImportNode, - '$t_cjs_temp_default_import' - ); - specifiers.push(defaultImportNode); - } + let usedNames = []; - const importDeclaration = t.importDeclaration( - specifiers, - t.stringLiteral(source) - ); + if (name) { + let binding = path.scope.getBinding(name); + + binding.referencePaths.every((rPath) => { + let {parent} = rPath; + + if (!t.isMemberExpression(parent)) { + usedNames = []; + return; + } else { + let proKey = getStaticMemberPro(parent); + + if (proKey === false) { + usedNames = []; + return; + } - this.state.globalESMImports.set(importDeclaration, [ - path.find((path) => { - return t.isProgram(path.parentPath); - }), - ]); + usedNames.push(proKey); + return true; + } + }); + + usedNames = unique(usedNames); + usedNames = usedNames.filter( + (n) => n !== 'default' + ); + } + + if (usedNames.length) { + usedNames.forEach((n) => { + requireNames.add(n); + }); + } else { + requireNames.add('default'); + } + } } }, }, @@ -343,62 +241,34 @@ class TransformCommonJs { AssignmentExpression: { enter: (path) => { - if (path.node.$t_ignore) { - return; - } - - path.node.$t_ignore = true; - let generateExportNode = (path, name) => { let exportName = name; let rightNode = path.node.right; if (t.isIdentifier(rightNode)) { - let exportNamedDeclaration = - t.exportNamedDeclaration(null, [ - t.exportSpecifier( - t.identifier(rightNode.name), - t.identifier(exportName) - ), - ]); - this.state.globalESMExports.set( - exportNamedDeclaration, - [ - path.find((path) => { - return t.isProgram(path.parentPath); - }), - ] + this.state.cjsExportModules.set( + exportName, + path.find((path) => { + return t.isProgram(path.parentPath); + }) ); } else { let id = - path.scope.generateUidIdentifierBasedOnNode( - rightNode, - exportName - ); + path.scope.generateUidIdentifier(exportName); let declaration = t.variableDeclaration('let', [ t.variableDeclarator(id, rightNode), ]); - let declarationPath = - path.insertBefore(declaration)[0]; - path.scope.registerBinding('let', declarationPath); + + path.insertBefore(declaration); let rightPath = path.get('right'); rightPath.replaceWith(id); - let exportNamedDeclaration = - t.exportNamedDeclaration(null, [ - t.exportSpecifier( - id, - t.identifier(exportName) - ), - ]); - this.state.globalESMExports.set( - exportNamedDeclaration, - [ - path.find((path) => { - return t.isProgram(path.parentPath); - }), - ] + this.state.cjsExportModules.set( + exportName, + path.find((path) => { + return t.isProgram(path.parentPath); + }) ); } }; @@ -415,7 +285,7 @@ class TransformCommonJs { const moduleBinding = path.scope.getBinding('module'); const exportsBinding = path.scope.getBinding('exports'); - // Something like `module.exports.namedExport = true;`. + // module.exports.x = 1; 不包含子属性 module.exports.x.y = 1; if ( t.isMemberExpression(path.node.left.object) && path.node.left.object.object.name === 'module' @@ -424,27 +294,28 @@ class TransformCommonJs { return; } - this.state.isCJS = true; - if ( - getStaticMemberProValue( - path.node.left.object - ) === 'exports' + getStaticMemberPro(path.node.left.object) === + 'exports' ) { - let name = getStaticMemberProValue( - path.node.left - ); + let name = getStaticMemberPro(path.node.left); // 动态导出,不转换 if (name === false) { return; } + if (this.ingorekeys.includes(name)) { + return; + } + + this.state.isCJS = true; + generateExportNode(path, name); } } else if (path.node.left.object.name === 'exports') { - // Check for regular exports - let name = getStaticMemberProValue(path.node.left); + // exports.x = 1; 不包含子属性 exports.x.y = 1; + let name = getStaticMemberPro(path.node.left); if ( exportsBinding || // If export is named "default" leave as is. @@ -457,6 +328,10 @@ class TransformCommonJs { return; } + if (this.ingorekeys.includes(name)) { + return; + } + this.state.isCJS = true; generateExportNode(path, name); @@ -468,19 +343,17 @@ class TransformCommonJs { MemberExpression: { enter: (path) => { if ( - path.node.$t_ignore2 || - this.state.isDynamicUsedExportsProperty + this.state.isDynamicUsedExportsProperty || + this.state.isUsedExportsObject ) { return; } - path.node.$t_ignore2 = true; - const moduleBinding = path.scope.getBinding('module'); const exportsBinding = path.scope.getBinding('exports'); let addUsedExports = () => { - let exportsProVal = getStaticMemberProValue(path.node); + let exportsProVal = getStaticMemberPro(path.node); // 动态访问了 exports 上的属性 if (exportsProVal === false) { @@ -491,12 +364,21 @@ class TransformCommonJs { this.state.usedExports.add(exportsProVal); }; + // 连等情况 + // let a = exports.x = 1,返回true,不算对x的引用,可直接删除exports.x + // let a = exports.x.y = 1, 返回false,算对x的引用,不会删除exports.x let checkIsAssignmentExpressionLeft = () => { let parentPath = path.parentPath; + + if (!t.isAssignmentExpression(parentPath)) { + return false; + } + let leftPath = parentPath.get('left'); return leftPath === path; }; + // module.exports.x if ( t.isMemberExpression(path.node.object) && path.node.object.object.name === 'module' @@ -509,7 +391,7 @@ class TransformCommonJs { return; } - let staticModuleProVal = getStaticMemberProValue( + let staticModuleProVal = getStaticMemberPro( path.node.object ); @@ -527,6 +409,7 @@ class TransformCommonJs { addUsedExports(); } else if (path.node.object.name === 'exports') { + // exports.x if (exportsBinding) { return; } @@ -536,11 +419,93 @@ class TransformCommonJs { } addUsedExports(); + } else if (path.node.object.name === 'module') { + // 直接使用 module.exports 对象整体 + if (moduleBinding) { + return; + } + + let staticModuleProVal = getStaticMemberPro(path.node); + + if (staticModuleProVal !== 'exports') { + return; + } + + // module.exports.x 情况 + // 不算对 module.exports 整体的使用 + if (t.isMemberExpression(path.parentPath)) { + return; + } + + // 到这里该语句一定严格是 module.exports + // 判断是否使用 + if (!that.checkUsed(path)) { + return; + } + + this.state.isUsedExportsObject = true; + } + }, + }, + + Identifier: { + enter: (path) => { + if ( + this.state.isDynamicUsedExportsProperty || + this.state.isUsedExportsObject + ) { + return; + } + + // 直接使用 exports 对象整体 + if ( + // 是exports + path.node.name === 'exports' && + // 父节点不是对象属性访问,例如:module.exports + !t.isMemberExpression(path.parentPath) && + // 作用域无 binding exports + !path.scope.getBinding('exports') && + that.checkUsed(path) + ) { + this.state.isUsedExportsObject = true; } }, }, }); } + + // 检查是否赋值给其他变量 + checkUsed(path) { + let parentPath = path.parentPath; + + // 处于等式左边,且右边不为 Identifier + // 即语句类似于:exports = {} + + // 且该语句没有赋值给其他语句,例如: + // let a = exports = {} + // a = exports = {} + // {a: exports = {}} + // [exports = {}] 等等 + + // 这里没有去一一判断,而是作了简单处理 + // 判断 exports = {} 的父节点为作用域语句,例如: + // function(){exports = {}} + // if(a){exports = {}} + // 但这会造成漏判,例如: + // if(exports = {}){} + // 并没有将 exports 赋值给其他变量,但这里拦截不了 + if ( + t.isAssignmentExpression(parentPath) && + parentPath.get('left') === path && + !t.isIdentifier(parentPath.get('right')) && + // 父节点是赋值语句,且父节点直接在作用域语句中 + t.isScopable(parentPath.parentPath) + ) { + return false; + } + + return true; + } } module.exports = { diff --git a/packages/wxa-cli/src/tree-shake/test.js b/packages/wxa-cli/src/tree-shake/test.js new file mode 100644 index 00000000..e1a47575 --- /dev/null +++ b/packages/wxa-cli/src/tree-shake/test.js @@ -0,0 +1,25 @@ +const generate = require('@babel/generator').default; +const traverse = require('@babel/traverse').default; +const {parse} = require('@babel/parser'); +let code = ``; + +code = ` +let a = require('/a'); + +a.x; +a.y; +a.default.u + +let n ='n'; +a[n]; + +let b = a;`; + +let ast = parse(code, {sourceType: 'unambiguous'}); +traverse(ast, { + enter(path) { + let scope = path.scope; + console.log(path.scope); + }, +}); + diff --git a/packages/wxa-cli/src/tree-shake/util.js b/packages/wxa-cli/src/tree-shake/util.js index 52dadc2b..68b89f51 100644 --- a/packages/wxa-cli/src/tree-shake/util.js +++ b/packages/wxa-cli/src/tree-shake/util.js @@ -3,7 +3,9 @@ let path = require('path'); let mkdirp = require('mkdirp'); const {parse} = require('@babel/parser'); const t = require('@babel/types'); +const traverse = require('@babel/traverse').default; let findRoot = require('find-root'); +let config = require('./config'); function readFile(p) { let rst = ''; @@ -58,7 +60,7 @@ function getPkgConfig(npmSrc, lib) { */ let cwd = process.cwd(); -function resolveDepSrc({fileSrc, depSrc, root, alias}) { +function resolveDepSrc({fileSrc, depSrc, root, alias, npm}) { let getDepAbsoulte = (src) => { if (isDir(src)) { return path.join(src, 'index.js'); @@ -101,7 +103,7 @@ function resolveDepSrc({fileSrc, depSrc, root, alias}) { return getDepAbsoulte(path.resolve(fileDir, depSrc)); } - let npmSrc = path.join(cwd, 'node_modules'); + let npmSrc = path.join(cwd, npm); let absoluteSrc = path.join(npmSrc, depSrc); if (!absoluteSrc.endsWith('.js')) { @@ -127,70 +129,137 @@ function resolveDepSrc({fileSrc, depSrc, root, alias}) { return getDepAbsoulte(path.join(npmSrc, depSrc, main)); } -function parseESCode(code, plugins = [], options) { - plugins = [ - ['decorators', {decoratorsBeforeExport: true}], - 'classProperties', - 'jsx', - 'typescript', - 'exportNamespaceFrom', - 'exportDefaultFrom', - 'objectRestSpread', - ...plugins, - ]; - - return parse(code, { - plugins, - sourceType: 'unambiguous', - ...options, +function parseESCode(code) { + return parse(code, config.parseOptions); +} + +function isChildNode(parent, child) { + if (parent === child) { + return true; + } + + let is = false; + + traverse(parent, { + noScope: true, + enter(path) { + let {node} = path; + if (node === child) { + is = true; + path.stop(); + } + }, }); + + return is; } -function dceDeclaration(scope, trackReferences = false) { +function dceDeclaration(scope) { let hasRemoved = false; - Object.entries(scope.bindings).forEach(([name, binding]) => { - // 类似于let a = function ff(){} - // ff 是函数内部作用域的binding,ff不应该被删除 - if (t.isFunctionExpression(binding.path)) { - return; - } - if (!binding.referenced) { - scope.removeOwnBinding(name); - binding.path.remove(); - hasRemoved = true; - return; - } + // 删除节点并不会自动更新相关binding的referenced等信息 + // 这里是重新收集bindings信息 + scope.crawl(); - // 使用path.remove删除节点后 - // 并不会让 scope 中的 binding.referenced 等信息更新 - // 即使重新遍历也不会更新 - if (trackReferences) { - let canRemove = binding.referencePaths.every((reference) => { - let parentPath = reference; - while (parentPath) { - if (!parentPath.node) { - return true; + let removeObjectPattern = (binding) => { + let proPath = null; + + traverse(binding.path.node, { + noScope: true, + ObjectProperty: { + enter: (path) => { + if (path.node.value === binding.identifier) { + proPath = path; + path.stop(); } + }, + }, + }); - parentPath = parentPath.parentPath; - } + return proPath; + }; + + let remove = (name, scope, binding) => { + // console.log(name); + let removedPath = binding.path; + let bindingPath = binding.path; - return false; - }); + // let {x: x1} = {x: 1, y2: 2}; + if (t.isVariableDeclarator(bindingPath)) { + let id = bindingPath.node.id; - if (canRemove) { - scope.removeOwnBinding(name); - binding.path.remove(); - hasRemoved = true; + if (t.isObjectPattern(id)) { + removedPath = removeObjectPattern(binding) || removedPath; } } + + removedPath.remove(); + scope.removeOwnBinding(name); + hasRemoved = true; + }; + + Object.entries(scope.bindings).forEach(([name, binding]) => { + if (binding.referenced) { + return; + } + + let bindingPath = binding.path; + + // 类似于let a = function ff(){} + // ff 是函数内部作用域的binding,ff不应该被删除 + // if (t.isFunctionExpression(bindingPath)) { + // return; + // } + + // // try...catch(e),e没访问到时不该删除整个catch语句 + // if (t.isCatchClause(bindingPath)) { + // return; + // } + + // // function(a, b) {}; + // // let t = function({dataset: {name, opts={}}}, [asq, ttqw]) {}; + // // 函数的参数 + // if ( + // t.isFunctionExpression(bindingPath.parentPath) || + // t.isFunctionDeclaration(bindingPath.parentPath) + // ) { + // return; + // } + + // // let [zz, xx, cc] = [1, 2, 3]; + // // let {x: x1} = {x: 1, y2: 2}; + // if ( + // t.isVariableDeclarator(bindingPath) && + // t.isArrayPattern(bindingPath.node.id) + // ) { + // return; + // } + + // // 未知 + // if (t.isArrayPattern(bindingPath)) { + // return; + // } + + if ( + // 过滤 let [zz, xx, cc] = [1, 2, 3]; + // 变量声明语句可能有副作用,不能简单去除 + // 例如:let a = obj.x,obj.x 可能有访问器属性。其他连等情况等等 + // (t.isVariableDeclarator(bindingPath) && + // !t.isArrayPattern(bindingPath.node.id)) || + t.isClassDeclaration(bindingPath) || + t.isFunctionDeclaration(bindingPath) || + t.isImportDefaultSpecifier(bindingPath) || + t.isImportNamespaceSpecifier(bindingPath) || + t.isImportSpecifier(bindingPath) + ) { + remove(name, scope, binding); + } }); // 处理声明之间循环引用 // 当一个声明未被使用时,那该声明所引用的其他声明不算真正使用 if (hasRemoved) { - dceDeclaration(scope, true); + dceDeclaration(scope); } } @@ -205,10 +274,16 @@ function dceDeclaration(scope, trackReferences = false) { // }) // ); +function unique(ary) { + return [...new Set(ary)]; +} + module.exports = { readFile, writeFile, resolveDepSrc, parseESCode, dceDeclaration, + isChildNode, + unique, }; From 94b6e05409f8a9daa8fb9acc42eb9db63e323d76 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Sun, 11 Jul 2021 22:33:14 +0800 Subject: [PATCH 12/20] =?UTF-8?q?feat:=20=E9=87=8D=E5=86=99tree=20shake?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/example/cjs1.js | 67 ++--- packages/wxa-cli/example/shaking/cjs1.js | 12 +- packages/wxa-cli/example/shaking/user.js | 5 +- packages/wxa-cli/example/shaking/user2.js | 2 + packages/wxa-cli/example/user.js | 20 +- packages/wxa-cli/example/user2.js | 8 + packages/wxa-cli/src/tree-shake/graph.js | 53 ++-- packages/wxa-cli/src/tree-shake/index.js | 249 ++++++++++++------ .../src/tree-shake/tansform-commonJS.js | 27 +- packages/wxa-cli/src/tree-shake/util.js | 205 +++++++------- 10 files changed, 378 insertions(+), 270 deletions(-) create mode 100644 packages/wxa-cli/example/shaking/user2.js create mode 100644 packages/wxa-cli/example/user2.js diff --git a/packages/wxa-cli/example/cjs1.js b/packages/wxa-cli/example/cjs1.js index b7ff0eec..f2fbbafe 100644 --- a/packages/wxa-cli/example/cjs1.js +++ b/packages/wxa-cli/example/cjs1.js @@ -1,12 +1,10 @@ -let fn1= require('./cjs2').fn1; - +let fn1 = require('./cjs2').fn1; fn1(); - -Object.defineProperty(exports, '__esModule', { - value: true, -}); +// Object.defineProperty(exports, '__esModule', { +// value: true, +// }); exports.getFiles = getFiles; // exports.getConfig = getConfig; module.exports.readFile = readFile; @@ -26,17 +24,16 @@ exports.getClassSet = getClassSet; exports.addClass = addClass; exports.removeClass = removeClass; -module.exports ={getFiles}; - +module.exports = {getFiles}; function getFiles(dir = process.cwd(), prefix = '') { let rst = []; - exports.rst= rst; + exports.rst = rst; - let aaaa= 'aaa'; + let aaaa = 'aaa'; // exports[aaaa] = aaaa; - + // let ttt= require('sss'); // console.log(ttt); @@ -54,44 +51,28 @@ function getFiles(dir = process.cwd(), prefix = '') { // return config; // } -function readFile(p) { - -} - -function writeFile(p, data) { - -} - -function isFile(p) { - -} - -function isDir(p) { +function readFile(p) {} -} +function writeFile(p, data) {} -function getRelative(opath) { - -} +function isFile(p) {} -function getDistPath(opath, ext, src, dist) { +function isDir(p) {} -} +function getRelative(opath) {} -function copy(from, to) { - -} +function getDistPath(opath, ext, src, dist) {} -function amazingCache(params, needCache) { +function copy(from, to) {} -} +function amazingCache(params, needCache) {} function applyPlugins(plugins, compiler) { if (plugins == null) return; // console.log(plugins); if (typeof plugins !== 'object') { -throw new Error('wxa配置文件有误,plugins'); -} + throw new Error('wxa配置文件有误,plugins'); + } if (!Array.isArray(plugins)) plugins = [plugins]; plugins.forEach((plugin) => plugin.apply(compiler)); } @@ -100,11 +81,9 @@ function isEmpty(n) { return n == null || n === ''; } -function getHash(filepath) { -} +function getHash(filepath) {} -function getHashWithString(content) { -} +function getHashWithString(content) {} function promiseSerial(funs) { return funs.reduce((promise, fun) => { @@ -137,8 +116,4 @@ function removeClass(classStr, destClass) { } // # sourceMappingURL=utils.js.map -exports.a=function m() { - -}; - - +exports.a = function m() {}; diff --git a/packages/wxa-cli/example/shaking/cjs1.js b/packages/wxa-cli/example/shaking/cjs1.js index 7aac95b8..5e016891 100644 --- a/packages/wxa-cli/example/shaking/cjs1.js +++ b/packages/wxa-cli/example/shaking/cjs1.js @@ -1,13 +1,13 @@ let fn1 = require('./cjs2').fn1; -fn1(); -Object.defineProperty(exports, '__esModule', { - value: true -}); +fn1(); // Object.defineProperty(exports, '__esModule', { +// value: true, +// }); + exports.writeFile = writeFile; exports.isFile = isFile; module.exports = { - getFiles + getFiles, }; function getFiles(dir = process.cwd(), prefix = '') { @@ -30,4 +30,4 @@ function writeFile(p, data) {} function isFile(p) {} -let _m = function m() {}; \ No newline at end of file +let _a = function m() {}; diff --git a/packages/wxa-cli/example/shaking/user.js b/packages/wxa-cli/example/shaking/user.js index 58f0c873..59320064 100644 --- a/packages/wxa-cli/example/shaking/user.js +++ b/packages/wxa-cli/example/shaking/user.js @@ -1,3 +1,4 @@ +import './user2'; export {}; function getAge(params) {} @@ -8,4 +9,6 @@ let mm1 = 1, c = function mm2(params) {}; export {}; -export {}; \ No newline at end of file +export {}; +export {}; +export {} from './user2'; \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/user2.js b/packages/wxa-cli/example/shaking/user2.js new file mode 100644 index 00000000..f4e5405f --- /dev/null +++ b/packages/wxa-cli/example/shaking/user2.js @@ -0,0 +1,2 @@ +export {}; +export {}; \ No newline at end of file diff --git a/packages/wxa-cli/example/user.js b/packages/wxa-cli/example/user.js index cfcf9a94..fd96d1ef 100644 --- a/packages/wxa-cli/example/user.js +++ b/packages/wxa-cli/example/user.js @@ -1,21 +1,19 @@ -export function getName() { - -} +import {fn1 as fn11} from './user2'; -export default function getAge(params) { - -} +export function getName() {} + +export default function getAge(params) {} // let a =1; // export default a; // eslint-disable-next-line one-var -export let mm1 =1, c=function mm2(params) { -}; +export let mm1 = 1, + c = function mm2(params) {}; -function fn2(params) { - -} +function fn2(params) {} export {fn2}; +export {fn11}; +export {fn2 as fn22} from './user2'; diff --git a/packages/wxa-cli/example/user2.js b/packages/wxa-cli/example/user2.js new file mode 100644 index 00000000..3d3f9131 --- /dev/null +++ b/packages/wxa-cli/example/user2.js @@ -0,0 +1,8 @@ +export function fn1() { + +} + +export function fn2() { + +} + diff --git a/packages/wxa-cli/src/tree-shake/graph.js b/packages/wxa-cli/src/tree-shake/graph.js index 7a7a09d3..7a32eee1 100644 --- a/packages/wxa-cli/src/tree-shake/graph.js +++ b/packages/wxa-cli/src/tree-shake/graph.js @@ -95,9 +95,9 @@ class Graph { let store = (name, path, node) => { if (isRoot) { - path.$extReferences = ['root']; + path.$extReferences = new Set().add('root'); } else { - path.$extReferences = []; + path.$extReferences = new Set(); } let expSrc = this.getExpSrc(node, src); exports[expSrc] = exports[expSrc] || {}; @@ -312,28 +312,39 @@ class Graph { * } */ - transformCommonJs.state.cjsRequireModules.forEach( - (names, requireSrc) => { - let abSrc = this.getAbsolutePath(src, requireSrc); + if (transformCommonJs) { + transformCommonJs.state.cjsRequireModules.forEach( + (names, requireSrc) => { + let abSrc = this.getAbsolutePath(src, requireSrc); + + imports[abSrc] = imports[abSrc] || {}; + Array.from(names).forEach((name) => { + if (name === 'default') { + imports[abSrc].default = 'custom_import_name'; + imports[abSrc]['*'] = 'custom_import_name'; + return; + } - imports[abSrc] = imports[abSrc] || {}; - Array.from(names).forEach((name) => { - if (name === 'default') { - imports[abSrc].default = 'custom_import_name'; - imports[abSrc]['*'] = 'custom_import_name'; - return; - } + imports[abSrc][name] = 'custom_import_name'; + }); + } + ); - imports[abSrc][name] = 'custom_import_name'; - }); - } - ); + transformCommonJs.state.cjsExportModules.forEach( + (path, name) => { + exports[src] = exports[src] || {}; + exports[src][name] = path; + path.$isCjsExport = true; + if (isRoot) { + path.$extReferences = new Set().add('root'); + } else { + path.$extReferences = new Set(); + } - transformCommonJs.state.cjsExportModules.forEach((path, name) => { - exports[src] = imports[src] || {}; - exports[src][name] = path; - path.$isCjsExport = true; - }); + // console.log('s:', name, path.toString()); + } + ); + } let dep = { src, diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index 05a255b1..d6d7dd49 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -10,7 +10,7 @@ let {Graph} = require('./graph'); * 但如果用require去引入一个export函数变量,这里并不能分析到这个export函数变量被使用过(所以不能去 require 一个 export) */ -let chain = {}; +let chains = {}; function shake(dep) { if (dep._shook) { @@ -23,29 +23,10 @@ function shake(dep) { console.log('shake src', depSrc); let fileExportChain = []; - chain[depSrc] = fileExportChain; - let nameInExport = new Map(); - - // let markExport = (fileExportChain) => { - // Object.values(fileExportChain).forEach(([name, chainInfo]) => {}); - // }; + chains[depSrc] = fileExportChain; let collectExportChain = (dep, childSrc, currentChain) => { if (currentChain.length) { - let nextChain = []; - - let setCurrentChain = (chainNode, childName, path) => { - let childChainNode = { - name: childName, - path, - children: [], - parent: chainNode, - }; - chainNode.children.push(childChainNode); - nextChain.push(childChainNode); - path.$chain - }; - let child = dep.children.find((child) => child.src === childSrc); let exportsArray = Object.entries(child.exports); let localIndex = exportsArray.findIndex( @@ -59,8 +40,28 @@ function shake(dep) { } let usedExports = {}; + let nextChain = []; + + let setCurrentChain = (chainNode, childName, path) => { + let childChainNode = { + name: childName, + path, + children: [], + parent: chainNode, + dep: child, + }; + chainNode.children.push(childChainNode); + nextChain.push(childChainNode); + path.$chain = { + [childName]: childChainNode, + }; + }; + + let getExportLocalName = (path, defaultName) => { + if (path.$isCjsExport) { + return defaultName; + } - let getExportLocalName = (path) => { let local = path.node.local; if (local) { return local.name; @@ -79,7 +80,6 @@ function shake(dep) { let collect = (chainNode, path, src, defaultLocalName) => { let localName = ''; - let name = chainNode.name; if (defaultLocalName) { localName = defaultLocalName; @@ -87,19 +87,11 @@ function shake(dep) { localName = getExportLocalName(path); } - let names = nameInExport.get(path); - - if (names && names.has(localName)) { + if (path.$chain && path.$chain[localName]) { + chainNode.children.push(path.$chain[localName]); return; } - if (names) { - names.add(localName); - } else { - names = new Set(); - names.add(localName); - } - setCurrentChain(chainNode, localName, path); addUsedExport(src, localName, path); }; @@ -126,7 +118,7 @@ function shake(dep) { ); } } else { - let localName = getExportLocalName(path); + let localName = getExportLocalName(path, name); setCurrentChain( importAllChainNode, localName, @@ -159,7 +151,7 @@ function shake(dep) { if (name === 'default') { setCurrentChain(chainNode, 'dafault', path); } else { - let localName = getExportLocalName(path); + let localName = getExportLocalName(path, name); setCurrentChain(chainNode, localName, path); } return; @@ -185,7 +177,7 @@ function shake(dep) { Object.entries(usedExports).forEach((src, value) => { let childUsedNames = Object.keys(value); let childChain = childUsedNames.map((n) => { - return nextChain.find((chainNode) =>chainNode.name === n); + return nextChain.find((chainNode) => chainNode.name === n); }); collectExportChain(child, src, childChain); @@ -198,81 +190,170 @@ function shake(dep) { // } Object.entries(imports).forEach(([src, value]) => { - let usedNames = []; + let currentChain = []; Object.entries(value).forEach(([name, path]) => { - usedNames.push(name); - fileExportChain.push({ + let chainNode = { parent: null, name, path, children: [], - }); + dep, + }; + fileExportChain.push(chainNode); + currentChain.push(chainNode); }); - collectExportChain(dep, src, fileExportChain); + collectExportChain(dep, src, currentChain); }); // 根节点的export语句默认全部保留 // 所以还需要处理根节点的export语句(export {} from '') - // if (isRoot) { - // Object.entries(exports).forEach(([src, exportInfo]) => { - // if (src !== dep.src) { - // let usedNames = []; - // Object.entries(exportInfo).forEach(([name]) => { - // usedNames.push(name); - // }); - // collectExportChain(dep, usedNames, src); - // } - // }); - // } + if (isRoot) { + Object.entries(exports).forEach(([src, exportInfo]) => { + if (src !== dep.src) { + let currentChain = []; + + Object.entries(exportInfo).forEach(([name, path]) => { + let chainNode = { + parent: null, + name, + path, + children: [], + dep, + }; + fileExportChain.push(chainNode); + currentChain.push(chainNode); + }); - dep._shook = true; + collectExportChain(dep, src, currentChain); + } + }); + } + + let markExport = () => { + let visitedChainNodes = []; + + let findLastChainNode = (chainNode) => { + // 循环依赖 + if (visitedChainNodes.includes(chainNode)) { + return; + } + + visitedChainNodes.push(chainNode); + + if (!chainNode.children.length) { + let exportPath = chainNode.path; + + if (exportPath.node && !exportPath.node.source) { + visitedChainNodes.forEach((visitedNode, index) => { + // 第一个节点是import节点或者root的export节点 + // 跳过 + if (index === 0) { + return; + } + + let {path} = visitedNode; + + path.$extReferences.add(visitedChainNodes[0].path); + }); + } + } else { + chainNode.children.forEach((child) => { + findLastChainNode(child); + }); + } + + visitedChainNodes.pop(); + }; + + fileExportChain.forEach((chainNode) => { + findLastChainNode(chainNode); + }); + }; + + markExport(); + dep._shook = true; dep.children.forEach((child) => shake(child)); } -function remove(dep) { - if (dep._removed) { +let noReferencedExports = []; + +function collectNotReferencedExports(dep) { + if (dep._colletced) { return; } - let {topScope, exports, src} = dep; - - let transformCommonJs = dep.transformCommonJs; - - console.log('remove', src); + let {exports, src} = dep; + console.log('colletced', src); // if (src.endsWith('ZY\\models\\applyCenter.model.js')) { // console.log('ss'); // } - /** - * 遍历exports,shake 标志表示该节点是否被外部有效的 import(即import的方法变量被使用过) - * 如果shake=1,表示没有被有效import过 - * _usedByNodes只存在于声明语句上,表示该声明语句被哪些identifier节点使用过。 - * 在导出语句中: - * 只有类似有name的函数变量(export function a(){} export default function a(){}),这样的导出节点才会有_usedByNodes - * shake=1且_usedByNodes不存在,表示该export节点即不被外部有效import,也不会被内部使用 - * shake=1且_usedByNodes存在且有值,表示该节点不被外部有效import,但被内部使用 - */ - Object.entries(exports).forEach(([src, value]) => { Object.entries(value).forEach(([name, path]) => { - if (path._shake === 1) { - if (path.$isCjsExport) { - transformCommonJs.deleteCJSExport(name); - } - path.remove(); + if (!path.$extReferences.size) { + noReferencedExports.push({path, dep, name}); } }); }); - dceDeclaration(topScope); + dep._colletced = true; - dep._removed = true; + dep.children.forEach((child) => collectNotReferencedExports(child)); +} - dep.children.forEach((child) => remove(child)); +function remove() { + let visitedChainNodes = []; + let removeExtReference = (chainNode, importPath) => { + // 循环依赖 + if (visitedChainNodes.includes(chainNode)) { + return; + } + + visitedChainNodes.push(chainNode); + chainNode.children.forEach((childNode) => { + childNode.path.$extReferences.delete(importPath); + + if (childNode.path.$extReferences.size === 0) { + noReferencedExports.push({ + path: childNode.path, + dep: childNode.dep, + name: childNode.name, + }); + } + + removeExtReference(childNode, importPath); + }); + visitedChainNodes.pop(); + }; + + for (let i = 0; i < noReferencedExports.length; i++) { + const {path: exportPath, dep, name} = noReferencedExports[i]; + let {transformCommonJs, topScope, src} = dep; + + if (exportPath.$isCjsExport) { + transformCommonJs.deleteCJSExport(name); + } else { + exportPath.remove(); + } + + let importPaths = dceDeclaration(topScope); + + if (importPaths.length) { + let chain = chains[src]; + + importPaths.forEach((importPath) => { + let chainNode = chain.find( + (chainNode) => chainNode.path === importPath + ); + + removeExtReference(chainNode, importPath); + }); + } + } } function output(dep) { @@ -361,9 +442,14 @@ function treeShake(options = {}) { console.log('shook'); + graph.roots.forEach((root) => { + collectNotReferencedExports(root); + }); + + remove(); + let contents = {}; graph.roots.forEach((root) => { - remove(root); contents = {...contents, ...output(root)}; }); @@ -377,7 +463,10 @@ module.exports = { console.time('end'); let path = require('path'); let entrySrc = path.resolve(__dirname, '../../example/index.js'); -treeShake([{src: entrySrc}]); +treeShake({ + entry: [{src: entrySrc}], + commonJS: {enable: true}, +}); console.timeEnd('end'); // function name(params) { diff --git a/packages/wxa-cli/src/tree-shake/tansform-commonJS.js b/packages/wxa-cli/src/tree-shake/tansform-commonJS.js index b530ca53..3ff503c9 100644 --- a/packages/wxa-cli/src/tree-shake/tansform-commonJS.js +++ b/packages/wxa-cli/src/tree-shake/tansform-commonJS.js @@ -65,20 +65,25 @@ class TransformCommonJs { // 如果一个模块被其他模块动态导入 // 不对这个模块做任何处理 if (dynamicRequireTargets.includes(src) || !config.commonJS.enable) { - return {src, code}; + return; } this.ingorekeys = config.commonJS.ingoreKeys; this.transform(this.ast, options); - console.log('cjsRequireModules', this.state.cjsRequireModules); - console.log('usedExports', this.state.usedExports); - console.log( - 'isDynamicUsedExportsProperty', - this.state.isDynamicUsedExportsProperty - ); - console.log('isUsedExportsObject', this.state.isUsedExportsObject); + if (this.state.isCJS) { + console.log('---------'); + console.log('cjsRequireModules', this.state.cjsRequireModules); + console.log('usedExports', this.state.usedExports); + console.log( + 'isDynamicUsedExportsProperty', + this.state.isDynamicUsedExportsProperty + ); + console.log('isUsedExportsObject', this.state.isUsedExportsObject); + // console.log('cjsExportModules', this.state.cjsExportModules); + console.log('---------'); + } } reset() { @@ -94,12 +99,14 @@ class TransformCommonJs { deleteCJSExport(exportName) { if ( this.state.isDynamicUsedExportsProperty || - this.state.usedExports.has(name) || + this.state.usedExports.has(exportName) || this.state.isUsedExportsObject ) { return; } + console.log(exportName); + Array.from(this.state.cjsExportModules).some(([name, cjsPath]) => { if (exportName === name) { cjsPath.remove(); @@ -499,7 +506,7 @@ class TransformCommonJs { parentPath.get('left') === path && !t.isIdentifier(parentPath.get('right')) && // 父节点是赋值语句,且父节点直接在作用域语句中 - t.isScopable(parentPath.parentPath) + t.isScopable(parentPath.parentPath.parentPath) ) { return false; } diff --git a/packages/wxa-cli/src/tree-shake/util.js b/packages/wxa-cli/src/tree-shake/util.js index 68b89f51..ad64f99a 100644 --- a/packages/wxa-cli/src/tree-shake/util.js +++ b/packages/wxa-cli/src/tree-shake/util.js @@ -155,112 +155,127 @@ function isChildNode(parent, child) { } function dceDeclaration(scope) { - let hasRemoved = false; - - // 删除节点并不会自动更新相关binding的referenced等信息 - // 这里是重新收集bindings信息 - scope.crawl(); - - let removeObjectPattern = (binding) => { - let proPath = null; - - traverse(binding.path.node, { - noScope: true, - ObjectProperty: { - enter: (path) => { - if (path.node.value === binding.identifier) { - proPath = path; - path.stop(); - } + let importPaths = []; + + let doDce = (scope) => { + let hasRemoved = false; + + // 删除节点并不会自动更新相关binding的referenced等信息 + // 这里是重新收集bindings信息 + scope.crawl(); + + let removeObjectPattern = (binding) => { + let proPath = null; + + traverse(binding.path.node, { + noScope: true, + ObjectProperty: { + enter: (path) => { + if (path.node.value === binding.identifier) { + proPath = path; + path.stop(); + } + }, }, - }, - }); + }); - return proPath; - }; + return proPath; + }; - let remove = (name, scope, binding) => { - // console.log(name); - let removedPath = binding.path; - let bindingPath = binding.path; + let remove = (name, scope, binding) => { + let removedPath = binding.path; + let bindingPath = binding.path; + + if ( + t.isImportDefaultSpecifier(bindingPath) || + t.isImportNamespaceSpecifier(bindingPath) || + t.isImportSpecifier(bindingPath) + ) { + importPaths.push(bindingPath); + } - // let {x: x1} = {x: 1, y2: 2}; - if (t.isVariableDeclarator(bindingPath)) { - let id = bindingPath.node.id; + // let {x: x1} = {x: 1, y2: 2}; + if (t.isVariableDeclarator(bindingPath)) { + let id = bindingPath.node.id; - if (t.isObjectPattern(id)) { - removedPath = removeObjectPattern(binding) || removedPath; + if (t.isObjectPattern(id)) { + removedPath = removeObjectPattern(binding) || removedPath; + } } - } - removedPath.remove(); - scope.removeOwnBinding(name); - hasRemoved = true; - }; + removedPath.remove(); + scope.removeOwnBinding(name); + hasRemoved = true; + }; - Object.entries(scope.bindings).forEach(([name, binding]) => { - if (binding.referenced) { - return; - } + Object.entries(scope.bindings).forEach(([name, binding]) => { + if (binding.referenced) { + return; + } - let bindingPath = binding.path; - - // 类似于let a = function ff(){} - // ff 是函数内部作用域的binding,ff不应该被删除 - // if (t.isFunctionExpression(bindingPath)) { - // return; - // } - - // // try...catch(e),e没访问到时不该删除整个catch语句 - // if (t.isCatchClause(bindingPath)) { - // return; - // } - - // // function(a, b) {}; - // // let t = function({dataset: {name, opts={}}}, [asq, ttqw]) {}; - // // 函数的参数 - // if ( - // t.isFunctionExpression(bindingPath.parentPath) || - // t.isFunctionDeclaration(bindingPath.parentPath) - // ) { - // return; - // } - - // // let [zz, xx, cc] = [1, 2, 3]; - // // let {x: x1} = {x: 1, y2: 2}; - // if ( - // t.isVariableDeclarator(bindingPath) && - // t.isArrayPattern(bindingPath.node.id) - // ) { - // return; - // } - - // // 未知 - // if (t.isArrayPattern(bindingPath)) { - // return; - // } - - if ( - // 过滤 let [zz, xx, cc] = [1, 2, 3]; - // 变量声明语句可能有副作用,不能简单去除 - // 例如:let a = obj.x,obj.x 可能有访问器属性。其他连等情况等等 - // (t.isVariableDeclarator(bindingPath) && - // !t.isArrayPattern(bindingPath.node.id)) || - t.isClassDeclaration(bindingPath) || - t.isFunctionDeclaration(bindingPath) || - t.isImportDefaultSpecifier(bindingPath) || - t.isImportNamespaceSpecifier(bindingPath) || - t.isImportSpecifier(bindingPath) - ) { - remove(name, scope, binding); + let bindingPath = binding.path; + + // 类似于let a = function ff(){} + // ff 是函数内部作用域的binding,ff不应该被删除 + // if (t.isFunctionExpression(bindingPath)) { + // return; + // } + + // // try...catch(e),e没访问到时不该删除整个catch语句 + // if (t.isCatchClause(bindingPath)) { + // return; + // } + + // // function(a, b) {}; + // // let t = function({dataset: {name, opts={}}}, [asq, ttqw]) {}; + // // 函数的参数 + // if ( + // t.isFunctionExpression(bindingPath.parentPath) || + // t.isFunctionDeclaration(bindingPath.parentPath) + // ) { + // return; + // } + + // // let [zz, xx, cc] = [1, 2, 3]; + // // let {x: x1} = {x: 1, y2: 2}; + // if ( + // t.isVariableDeclarator(bindingPath) && + // t.isArrayPattern(bindingPath.node.id) + // ) { + // return; + // } + + // // 未知 + // if (t.isArrayPattern(bindingPath)) { + // return; + // } + + if ( + // 过滤 let [zz, xx, cc] = [1, 2, 3]; + // 变量声明语句可能有副作用,不能简单去除 + // 例如:let a = obj.x,obj.x 可能有访问器属性。其他连等情况等等 + // (t.isVariableDeclarator(bindingPath) && + // !t.isArrayPattern(bindingPath.node.id)) || + t.isClassDeclaration(bindingPath) || + t.isFunctionDeclaration(bindingPath) || + t.isImportDefaultSpecifier(bindingPath) || + t.isImportNamespaceSpecifier(bindingPath) || + t.isImportSpecifier(bindingPath) + ) { + remove(name, scope, binding); + } + }); + + // 处理声明之间循环引用 + // 当一个声明未被使用时,那该声明所引用的其他声明不算真正使用 + if (hasRemoved) { + doDce(scope); } - }); + }; - // 处理声明之间循环引用 - // 当一个声明未被使用时,那该声明所引用的其他声明不算真正使用 - if (hasRemoved) { - dceDeclaration(scope); - } + doDce(scope); + + return importPaths; } // console.log( From 608ee73222e63256c8f3d7ea3af08f02dda2e020 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Wed, 14 Jul 2021 19:12:53 +0800 Subject: [PATCH 13/20] =?UTF-8?q?feat:=20=E6=95=B4=E7=90=86=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/example/shaking/cjs1.js | 9 +- packages/wxa-cli/example/shaking/cjs2.js | 4 +- packages/wxa-cli/example/shaking/index.js | 21 +- packages/wxa-cli/example/shaking/user.js | 7 +- packages/wxa-cli/package.json | 3 +- packages/wxa-cli/src/schedule.js | 62 ++- packages/wxa-cli/src/tree-shake/config.js | 27 +- packages/wxa-cli/src/tree-shake/graph.js | 145 +++--- packages/wxa-cli/src/tree-shake/index.js | 492 +----------------- .../{tansform-commonJS.js => shake-cjs.js} | 166 +++--- packages/wxa-cli/src/tree-shake/tree-shake.js | 441 ++++++++++++++++ packages/wxa-cli/src/tree-shake/util.js | 67 ++- 12 files changed, 735 insertions(+), 709 deletions(-) rename packages/wxa-cli/src/tree-shake/{tansform-commonJS.js => shake-cjs.js} (83%) create mode 100644 packages/wxa-cli/src/tree-shake/tree-shake.js diff --git a/packages/wxa-cli/example/shaking/cjs1.js b/packages/wxa-cli/example/shaking/cjs1.js index 5e016891..0bb3741a 100644 --- a/packages/wxa-cli/example/shaking/cjs1.js +++ b/packages/wxa-cli/example/shaking/cjs1.js @@ -7,13 +7,12 @@ fn1(); // Object.defineProperty(exports, '__esModule', { exports.writeFile = writeFile; exports.isFile = isFile; module.exports = { - getFiles, + getFiles }; function getFiles(dir = process.cwd(), prefix = '') { let rst = []; - exports.rst = rst; - let aaaa = 'aaa'; // exports[aaaa] = aaaa; + exports.rst = rst; // exports[aaaa] = aaaa; // let ttt= require('sss'); // console.log(ttt); // exports.addClass; @@ -28,6 +27,4 @@ function getFiles(dir = process.cwd(), prefix = '') { function writeFile(p, data) {} -function isFile(p) {} - -let _a = function m() {}; +function isFile(p) {} \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/cjs2.js b/packages/wxa-cli/example/shaking/cjs2.js index faf6661a..f6a7929f 100644 --- a/packages/wxa-cli/example/shaking/cjs2.js +++ b/packages/wxa-cli/example/shaking/cjs2.js @@ -1,5 +1,3 @@ function fn1(params) {} -exports.fn1 = fn1; - -let _fn = function fn4() {}; \ No newline at end of file +exports.fn1 = fn1; \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/index.js b/packages/wxa-cli/example/shaking/index.js index 327a1ba9..1e3e28b4 100644 --- a/packages/wxa-cli/example/shaking/index.js +++ b/packages/wxa-cli/example/shaking/index.js @@ -6,8 +6,7 @@ import { writeFile, isFile } from './cjs1'; writeFile(); isFile(); getName(); -let ssqqww = 1; // console.log(user); - +// console.log(user); console.log(getAge); let a = { x: 1 @@ -20,7 +19,6 @@ function m(x = 1, y) { ++a; t = 9; t + 5; - let qqq = 10; let ssqqww = 5; console.log(ssqqww); } @@ -32,13 +30,6 @@ try { console.log(a); } catch (error) {} -let ttt = function ({ - x: xxx, - y -}) {}; - -let sss = (a, b) => {}; - [1, 2, 3].forEach(function (item) {}); for (i = 0; i < 100; i++) {} @@ -81,16 +72,12 @@ let clearErrorMsg = function ({ opts = {} } } -}, [asq, ttqw], ppp) { - let asdf = 'p'; -}; +}, [asq, ttqw], ppp) {}; function aaa({ p1, p2 -}) { - let asdwqe = 'p'; -} +}) {} ; aaa(); @@ -126,6 +113,8 @@ export { mm }; class asf {} +// export {m as qqqqq, a as default}; +// export {x, y} from './a'; export default asf; ; export { Myclass }; // eslint-disable-next-line no-var diff --git a/packages/wxa-cli/example/shaking/user.js b/packages/wxa-cli/example/shaking/user.js index 59320064..dce4848e 100644 --- a/packages/wxa-cli/example/shaking/user.js +++ b/packages/wxa-cli/example/shaking/user.js @@ -3,10 +3,9 @@ export {}; function getAge(params) {} -export default getAge; - -let mm1 = 1, - c = function mm2(params) {}; +export default getAge; // let a =1; +// export default a; +// eslint-disable-next-line one-var export {}; export {}; diff --git a/packages/wxa-cli/package.json b/packages/wxa-cli/package.json index a5d39c3a..86e7530c 100644 --- a/packages/wxa-cli/package.json +++ b/packages/wxa-cli/package.json @@ -70,7 +70,8 @@ "promise.prototype.finally": "^3.1.0", "shelljs": "^0.8.3", "tapable": "^1.0.0", - "valid-url": "^1.0.9" + "valid-url": "^1.0.9", + "lodash": "^4.17.21" }, "publishConfig": { "access": "public" diff --git a/packages/wxa-cli/src/schedule.js b/packages/wxa-cli/src/schedule.js index 64a62b6f..3a298283 100644 --- a/packages/wxa-cli/src/schedule.js +++ b/packages/wxa-cli/src/schedule.js @@ -17,6 +17,7 @@ import DependencyResolver from './helpers/dependencyResolver'; import ProgressTextBar from './helpers/progressTextBar'; import Preformance from './helpers/performance'; import simplify from './helpers/simplifyObj'; +import {treeShake} from './tree-shake/index'; let debug = debugPKG('WXA:Schedule'); @@ -72,6 +73,7 @@ class Schedule { // if is mounting compiler, all task will be blocked. this.$isMountingCompiler = false; this.progress = new ProgressTextBar(this.current, wxaConfigs); + this.$depJsPending = []; // save all app configurations for compile time. // such as global components. @@ -120,17 +122,28 @@ class Schedule { async $doDPA() { let tasks = []; + while (this.$depPending.length) { let dep = this.$depPending.shift(); + if (!this.cmdOptions.watch && dep.src.endsWith('.js')) { + this.$depJsPending.push(dep); + } else { + tasks.push(this.$parse(dep)); + } + // debug('file to parse %O', dep); - tasks.push(this.$parse(dep)); } let succ = await Promise.all(tasks); if (this.$depPending.length === 0) { // dependencies resolve complete + if (!this.cmdOptions.watch) { + let sub = await this.$dojsDPA(); + return succ.concat(sub); + } + this.progress.clean(); return succ; } else { @@ -139,6 +152,53 @@ class Schedule { } } + async $dojsDPA() { + this.$depPending = this.$depJsPending; + this.$depJsPending = []; + let entries = this.$depPending.map((item)=>({src: item.src, content: item.content})); + console.time('shake'); + let contents = treeShake( + { + entry: entries, + resolveSrc: { + root: 'src', + alias: this.wxaConfigs.resolve.alias, + }, + commonJS: { + enable: true, + }, + } + ); + console.timeEnd('shake'); + + let run = async () => { + let tasks = []; + + while (this.$depPending.length) { + let dep = this.$depPending.shift(); + let content = contents[dep.src] && contents[dep.src].formattedCode; + if (content) { + dep.content = content; + } + + tasks.push(this.$parse(dep)); + } + + let succ = await Promise.all(tasks); + + if (this.$depPending.length === 0) { + // dependencies resolve complete + this.progress.clean(); + return succ; + } else { + let sub = await run(); + return succ.concat(sub); + } + }; + + return run(); + } + async $parse(dep) { if (dep.color === COLOR.COMPILED) return dep; if (dep.color === COLOR.CHANGED) dep.code = void(0); diff --git a/packages/wxa-cli/src/tree-shake/config.js b/packages/wxa-cli/src/tree-shake/config.js index 5ed7e593..8c3cb25a 100644 --- a/packages/wxa-cli/src/tree-shake/config.js +++ b/packages/wxa-cli/src/tree-shake/config.js @@ -1,16 +1,13 @@ module.exports = { - entry: [ - { - // 路径 - src: '', - // 文件内容(可选) - content: '', - }, - ], + // { + // src: '', // 路径 + // content: '', // 文件内容(可选) + // }, + entry: [], resolveSrc: { // '/a/b/c',绝对路径根目录 // 例如src, '/a/b/c' 转换为 /src/a/b/b - root: '', + root: 'src', // {'@': 'src'},路径别名 alias: {}, npm: 'node_modules', @@ -18,23 +15,25 @@ module.exports = { commonJS: { enable: false, // 无法追踪动态引入的模块 - // 如果有模块被动态引入,需要在这里设置该模块路径 - // 将跳过对该模块的 cjs 转 esm + // 如果有模块被动态引入,需要在这里设置该模块文件路径 + // 将跳过对该文件的 tree shake dynamicRequireTargets: [], // 设置 exports 上的哪些属性不会被转换为 esm // 默认值有 '__esModule' - ingoreKeys: [], + ingoreKeys: ['__esModule'], }, parseOptions: { plugins: [ ['decorators', {decoratorsBeforeExport: true}], 'classProperties', - 'jsx', - 'typescript', 'exportNamespaceFrom', 'exportDefaultFrom', 'objectRestSpread', ], sourceType: 'unambiguous', }, + generateOptions: { + decoratorsBeforeExport: true, + }, + debug: false, }; diff --git a/packages/wxa-cli/src/tree-shake/graph.js b/packages/wxa-cli/src/tree-shake/graph.js index 7a32eee1..55769847 100644 --- a/packages/wxa-cli/src/tree-shake/graph.js +++ b/packages/wxa-cli/src/tree-shake/graph.js @@ -5,9 +5,10 @@ const { resolveDepSrc, parseESCode, dceDeclaration, + log, } = require('./util'); let config = require('./config'); -let {TransformCommonJs} = require('./tansform-commonJS'); +let {CommonJS} = require('./shake-cjs'); class Graph { constructor(entries) { @@ -151,12 +152,15 @@ class Graph { if (node.specifiers && node.specifiers.length) { storeSpecifiers(path, node); } else { - let {specifiers, declarationPath} = - transformExportDeclarationToSpecifiers(path); + // 类似于export function mm(){} + // 单独声明 function mm(){},并export default mm + let { + specifiers, + declarationPath, + } = transformExportDeclarationToSpecifiers(path); + + path.insertBefore(declarationPath.node); - let newDeclarationPath = path.insertBefore( - declarationPath.node - )[0]; let exportNamedDeclaration = t.exportNamedDeclaration( null, specifiers @@ -164,14 +168,8 @@ class Graph { let newExportPath = path.insertAfter( exportNamedDeclaration )[0]; - // 删除声明节点会同时删除相应binding - path.remove(); - // 注册binding - // 注册binding是根据path来注册 - // path.scope.registerBinding(declarationPath.node.kind || 'hoisted', newDeclarationPath); - // 注册binding,并不会自动更新相应binding的referencePaths等信息,调用crawl更新 - // path.scope.crawl(); + path.remove(); storeSpecifiers(newExportPath, node); } }, @@ -179,26 +177,37 @@ class Graph { ExportDefaultDeclaration: { enter: (path) => { let {node} = path; - let declarationNode = node.declaration; - let exportPath = path; - - // TODO,未处理 export default a=1 这类表达式 - // 类似于export default function mm(){} - // 单独声明mm,并export default mm - if (declarationNode.id && declarationNode.id.name) { - let newDeclarationPath = - path.insertBefore(declarationNode)[0]; - let exportDefaultNode = t.exportDefaultDeclaration( - t.identifier(declarationNode.id.name) - ); - exportPath = path.insertAfter(exportDefaultNode)[0]; - path.remove(); - // 注册binding - // path.scope.registerBinding( declarationNode.kind || 'hoisted', newDeclarationPath); - // path.scope.crawl(); + let declarationPath = path.get('declaration'); + let declarationNode = declarationPath.node; + + // 类似于 export default function mm(){} + // 单独声明 mm,然后 export default mm + if ( + (t.isFunctionDeclaration(declarationNode) || + t.isClassDeclaration(declarationNode)) && + declarationNode.id && + declarationNode.id.name + ) { + path.insertBefore(declarationNode); + declarationPath.replaceWith(declarationNode.id); + } else if ( + !t.isFunctionDeclaration(declarationNode) && + !t.isClassDeclaration(declarationNode) && + !t.isIdentifier(declarationNode) + ) { + // 类似于 export default {} + // 单独声明 let _temp = {},然后 export default _temp + let id = path.scope.generateUidIdentifier(); + let declaration = t.variableDeclaration('let', [ + t.variableDeclarator(id, declarationNode), + ]); + path.insertBefore(declaration); + declarationPath.replaceWith(id); } - store('default', exportPath, node); + // 剩余情况:export default a, export default function(){} + + store('default', path, node); }, }, ExportAllDeclaration: { @@ -239,16 +248,11 @@ class Graph { content = entry.content; } - // if (src.endsWith('user.js')) { - // console.log('src', src); - // this.debug = true; - // } - if (analyzedFile[src]) { return analyzedFile[src]; } - - console.log('graph', src); + + log('graph', src); let code = content || readFile(src); let ast = parseESCode(code); @@ -257,7 +261,7 @@ class Graph { let topScope = null; - let transformCommonJs = new TransformCommonJs({src, code, ast}); + let commonjs = new CommonJS({src, code, ast}); let {visitor: exportVisitor, exports} = this.collectExport( src, @@ -275,10 +279,6 @@ class Graph { ...importVisitor, }); - // console.log(src); - // console.log('imports', imports); - // console.log('exports', exports); - // import * 和 export * 不包括default // export * from '' 和 export 本文件冲突,export 本文件优先级更高 // export * from '' 互相冲突,后export * from '' 优先 @@ -312,36 +312,37 @@ class Graph { * } */ - if (transformCommonJs) { - transformCommonJs.state.cjsRequireModules.forEach( - (names, requireSrc) => { - let abSrc = this.getAbsolutePath(src, requireSrc); - - imports[abSrc] = imports[abSrc] || {}; - Array.from(names).forEach((name) => { - if (name === 'default') { - imports[abSrc].default = 'custom_import_name'; - imports[abSrc]['*'] = 'custom_import_name'; - return; - } + commonjs.state.cjsRequireModules.forEach( + (names, requireSrc) => { + let abSrc = this.getAbsolutePath(src, requireSrc); - imports[abSrc][name] = 'custom_import_name'; - }); - } - ); + imports[abSrc] = imports[abSrc] || {}; + Array.from(names).forEach((name) => { + if (name === 'default') { + imports[abSrc].default = 'custom_import_name'; + imports[abSrc]['*'] = 'custom_import_name'; + return; + } - transformCommonJs.state.cjsExportModules.forEach( + imports[abSrc][name] = 'custom_import_name'; + }); + } + ); + + if (!commonjs.state.dynamicRequired) { + commonjs.state.cjsExportModules.forEach( (path, name) => { exports[src] = exports[src] || {}; exports[src][name] = path; path.$isCjsExport = true; + if (isRoot) { path.$extReferences = new Set().add('root'); } else { path.$extReferences = new Set(); } - // console.log('s:', name, path.toString()); + // log('cjsExportName', name, path.toString()); } ); } @@ -355,29 +356,9 @@ class Graph { children: [], topScope, isRoot, - transformCommonJs, + commonjs, }; - // const generate = require('@babel/generator').default; - // const {writeFile} = require('./util'); - // let path = require('path'); - // const {code: outputCode} = generate( - // ast, - // { - // /* options */ - // decoratorsBeforeExport: true, - // }, - // code - // ); - // writeFile( - // path.resolve( - // path.dirname(src), - // './shaking', - // path.basename(src) - // ), - // outputCode - // ); - analyzedFile[src] = dep; Object.keys(dep.imports).forEach((childSrc, index) => { diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index d6d7dd49..69e13006 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -1,398 +1,8 @@ -const generate = require('@babel/generator').default; -const {writeFile, dceDeclaration} = require('./util'); let config = require('./config'); - let {Graph} = require('./graph'); - -/** - * export node 有一个_shake标志,如果该export没有被import,或者被import后没有使用,_shake = 1 - * 在这里,遍历全局文件树,根据import和export关系,对没使用的export进行标记 - * 但如果用require去引入一个export函数变量,这里并不能分析到这个export函数变量被使用过(所以不能去 require 一个 export) - */ - -let chains = {}; - -function shake(dep) { - if (dep._shook) { - return; - } - - let {imports, exports, isRoot, src: depSrc} = dep; - - console.log('---'); - console.log('shake src', depSrc); - - let fileExportChain = []; - chains[depSrc] = fileExportChain; - - let collectExportChain = (dep, childSrc, currentChain) => { - if (currentChain.length) { - let child = dep.children.find((child) => child.src === childSrc); - let exportsArray = Object.entries(child.exports); - let localIndex = exportsArray.findIndex( - ([src]) => src == child.src - ); - let localExports = null; - let externalExports = [...exportsArray]; - - if (localIndex !== -1) { - localExports = externalExports.splice(localIndex, 1)[0]; - } - - let usedExports = {}; - let nextChain = []; - - let setCurrentChain = (chainNode, childName, path) => { - let childChainNode = { - name: childName, - path, - children: [], - parent: chainNode, - dep: child, - }; - chainNode.children.push(childChainNode); - nextChain.push(childChainNode); - path.$chain = { - [childName]: childChainNode, - }; - }; - - let getExportLocalName = (path, defaultName) => { - if (path.$isCjsExport) { - return defaultName; - } - - let local = path.node.local; - if (local) { - return local.name; - } - - return '*'; - }; - - let addUsedExport = (src, name, path) => { - usedExports[src] = usedExports[src] || {}; - - if (name) { - usedExports[src][name] = path; - } - }; - - let collect = (chainNode, path, src, defaultLocalName) => { - let localName = ''; - - if (defaultLocalName) { - localName = defaultLocalName; - } else { - localName = getExportLocalName(path); - } - - if (path.$chain && path.$chain[localName]) { - chainNode.children.push(path.$chain[localName]); - return; - } - - setCurrentChain(chainNode, localName, path); - addUsedExport(src, localName, path); - }; - - let importAllChainNode = currentChain.find( - (node) => node.name === '*' - ); - - if (importAllChainNode) { - let importDefaultChainNode = currentChain.find( - (node) => node.name === 'default' - ); - - let markedDefalut = false; - if (localExports) { - Object.entries(localExports[1]).forEach(([name, path]) => { - if (name === 'default') { - if (importDefaultChainNode) { - markedDefalut = true; - setCurrentChain( - importDefaultChainNode, - 'dafault', - path - ); - } - } else { - let localName = getExportLocalName(path, name); - setCurrentChain( - importAllChainNode, - localName, - path - ); - } - }); - } - - externalExports.forEach(([src, exportInfo]) => { - Object.entries(exportInfo).forEach(([name, path]) => { - if ( - name === 'default' && - importDefaultChainNode && - !markedDefalut - ) { - collect(importDefaultChainNode, path, src); - } else if (name !== 'default') { - collect(importAllChainNode, path, src); - } - }); - }); - } else { - currentChain.forEach((chainNode) => { - let name = chainNode.name; - if (localExports) { - let path = localExports[1][name]; - - if (path) { - if (name === 'default') { - setCurrentChain(chainNode, 'dafault', path); - } else { - let localName = getExportLocalName(path, name); - setCurrentChain(chainNode, localName, path); - } - return; - } - } - - externalExports.forEach(([src, exportInfo]) => { - let path = exportInfo[name]; - - if (path) { - collect(chainNode, path, src); - } - - path = exportInfo['*']; - - if (path) { - collect(chainNode, path, src, name); - } - }); - }); - } - - Object.entries(usedExports).forEach((src, value) => { - let childUsedNames = Object.keys(value); - let childChain = childUsedNames.map((n) => { - return nextChain.find((chainNode) => chainNode.name === n); - }); - - collectExportChain(child, src, childChain); - }); - } - }; - - // if (depSrc.endsWith('ZY\\models\\index.js')) { - // console.log('ssssss'); - // } - - Object.entries(imports).forEach(([src, value]) => { - let currentChain = []; - - Object.entries(value).forEach(([name, path]) => { - let chainNode = { - parent: null, - name, - path, - children: [], - dep, - }; - fileExportChain.push(chainNode); - currentChain.push(chainNode); - }); - - collectExportChain(dep, src, currentChain); - }); - - // 根节点的export语句默认全部保留 - // 所以还需要处理根节点的export语句(export {} from '') - if (isRoot) { - Object.entries(exports).forEach(([src, exportInfo]) => { - if (src !== dep.src) { - let currentChain = []; - - Object.entries(exportInfo).forEach(([name, path]) => { - let chainNode = { - parent: null, - name, - path, - children: [], - dep, - }; - fileExportChain.push(chainNode); - currentChain.push(chainNode); - }); - - collectExportChain(dep, src, currentChain); - } - }); - } - - let markExport = () => { - let visitedChainNodes = []; - - let findLastChainNode = (chainNode) => { - // 循环依赖 - if (visitedChainNodes.includes(chainNode)) { - return; - } - - visitedChainNodes.push(chainNode); - - if (!chainNode.children.length) { - let exportPath = chainNode.path; - - if (exportPath.node && !exportPath.node.source) { - visitedChainNodes.forEach((visitedNode, index) => { - // 第一个节点是import节点或者root的export节点 - // 跳过 - if (index === 0) { - return; - } - - let {path} = visitedNode; - - path.$extReferences.add(visitedChainNodes[0].path); - }); - } - } else { - chainNode.children.forEach((child) => { - findLastChainNode(child); - }); - } - - visitedChainNodes.pop(); - }; - - fileExportChain.forEach((chainNode) => { - findLastChainNode(chainNode); - }); - }; - - markExport(); - - dep._shook = true; - dep.children.forEach((child) => shake(child)); -} - -let noReferencedExports = []; - -function collectNotReferencedExports(dep) { - if (dep._colletced) { - return; - } - - let {exports, src} = dep; - console.log('colletced', src); - - // if (src.endsWith('ZY\\models\\applyCenter.model.js')) { - // console.log('ss'); - // } - - Object.entries(exports).forEach(([src, value]) => { - Object.entries(value).forEach(([name, path]) => { - if (!path.$extReferences.size) { - noReferencedExports.push({path, dep, name}); - } - }); - }); - - dep._colletced = true; - - dep.children.forEach((child) => collectNotReferencedExports(child)); -} - -function remove() { - let visitedChainNodes = []; - let removeExtReference = (chainNode, importPath) => { - // 循环依赖 - if (visitedChainNodes.includes(chainNode)) { - return; - } - - visitedChainNodes.push(chainNode); - chainNode.children.forEach((childNode) => { - childNode.path.$extReferences.delete(importPath); - - if (childNode.path.$extReferences.size === 0) { - noReferencedExports.push({ - path: childNode.path, - dep: childNode.dep, - name: childNode.name, - }); - } - - removeExtReference(childNode, importPath); - }); - visitedChainNodes.pop(); - }; - - for (let i = 0; i < noReferencedExports.length; i++) { - const {path: exportPath, dep, name} = noReferencedExports[i]; - let {transformCommonJs, topScope, src} = dep; - - if (exportPath.$isCjsExport) { - transformCommonJs.deleteCJSExport(name); - } else { - exportPath.remove(); - } - - let importPaths = dceDeclaration(topScope); - - if (importPaths.length) { - let chain = chains[src]; - - importPaths.forEach((importPath) => { - let chainNode = chain.find( - (chainNode) => chainNode.path === importPath - ); - - removeExtReference(chainNode, importPath); - }); - } - } -} - -function output(dep) { - let contents = {}; - - let run = (dep) => { - let {ast, code, src} = dep; - - if (dep._output) { - return; - } - - const {code: outputCode} = generate( - ast, - { - /* options */ - decoratorsBeforeExport: true, - }, - code - ); - - writeFile( - path.resolve(path.dirname(src), './shaking', path.basename(src)), - outputCode - ); - - contents[src] = outputCode; - - dep._output = true; - - dep.children.forEach((child) => { - run(child); - }); - }; - - run(dep); - - return contents; -} +let {TreeShake} = require('./tree-shake'); +let mergeWith = require('lodash/mergeWith'); +let isArray = require('lodash/isArray'); function setConfig(options) { if ( @@ -403,93 +13,39 @@ function setConfig(options) { throw new Error('Options entry is required'); } - config.entry = options.entry; - - if (options.resolveSrc) { - Object.assign(config.resolveSrc, options.resolveSrc); - } - - if (options.commonJS) { - Object.assign(config.commonJS, options.commonJS); - config.commonJS.ingoreKeys.push('__esModule'); - } - - if (options.parseOptions) { - if (options.parseOptions.plugins) { - config.parseOptions.plugins = [ - ...config.parseOptions.plugins, - ...options.parseOptions.plugins, - ]; - - delete options.parseOptions.plugins; + mergeWith(config, options, (objValue, srcValue) => { + if (isArray(objValue)) { + return objValue.concat(srcValue); } - - config.parseOptions = { - ...config.parseOptions, - ...options.parseOptions, - }; - } + }); } function treeShake(options = {}) { setConfig(options); let graph = new Graph(); - - graph.roots.forEach((root) => { - shake(root); - }); - - console.log('shook'); - - graph.roots.forEach((root) => { - collectNotReferencedExports(root); - }); - - remove(); - - let contents = {}; - graph.roots.forEach((root) => { - contents = {...contents, ...output(root)}; - }); - - return contents; + let treeShake = new TreeShake(graph.roots); + let files = treeShake.run(); + return files; } module.exports = { treeShake, }; -console.time('end'); -let path = require('path'); -let entrySrc = path.resolve(__dirname, '../../example/index.js'); -treeShake({ - entry: [{src: entrySrc}], - commonJS: {enable: true}, -}); -console.timeEnd('end'); - -// function name(params) { -// console.log(m); -// } - -// name(); -// const generate = require('@babel/generator').default; -// const traverse = require('@babel/traverse').default; -// const {parse} = require('@babel/parser'); -// let code = `exports.x=1;let t =exports`; -// let ast = parse(code, {sourceType: 'unambiguous'}); -// traverse(ast, { -// enter(path) { -// console.log(path.scope) - -// }, +// console.time('end'); +// let path = require('path'); +// const {writeFile} = require('./util'); +// let entrySrc = path.resolve(__dirname, '../../example/index.js'); +// let files = treeShake({ +// entry: [{src: entrySrc}], +// commonJS: {enable: true}, // }); -// console.log(generate( -// ast, -// { -// /* options */ -// }, -// code -// ).code); +// Object.values(files).forEach(({src, formattedCode}) => { +// writeFile( +// path.resolve(path.dirname(src), './shaking', path.basename(src)), +// formattedCode +// ); +// }); +// console.timeEnd('end'); diff --git a/packages/wxa-cli/src/tree-shake/tansform-commonJS.js b/packages/wxa-cli/src/tree-shake/shake-cjs.js similarity index 83% rename from packages/wxa-cli/src/tree-shake/tansform-commonJS.js rename to packages/wxa-cli/src/tree-shake/shake-cjs.js index 3ff503c9..5d7e2eae 100644 --- a/packages/wxa-cli/src/tree-shake/tansform-commonJS.js +++ b/packages/wxa-cli/src/tree-shake/shake-cjs.js @@ -1,19 +1,8 @@ -let path = require('path'); - const traverse = require('@babel/traverse').default; -const generate = require('@babel/generator').default; -const { - readFile, - writeFile, - parseESCode, - isChildNode, - unique, -} = require('./util'); +const {parseESCode, unique, log} = require('./util'); let t = require('@babel/types'); const config = require('./config'); -let options = {}; - function getStaticValue(node) { if (t.isStringLiteral(node) || t.isNumericLiteral(node)) { return node.value; @@ -27,7 +16,7 @@ function getStaticValue(node) { return false; } -// node: MemberExpression +// 获得 MemberExpression 节点的属性的静态值 function getStaticMemberPro(node) { if (node.computed) { return getStaticValue(node.property); @@ -36,7 +25,7 @@ function getStaticMemberPro(node) { return node.property.name; } -class TransformCommonJs { +class CommonJS { state = { // { // moduleName: exports Path @@ -54,6 +43,7 @@ class TransformCommonJs { usedExports: new Set(), isDynamicUsedExportsProperty: false, isUsedExportsObject: false, + dynamicRequired: false, }; constructor({src, code, ast}) { @@ -62,27 +52,31 @@ class TransformCommonJs { this.ast = ast || parseESCode(code); let dynamicRequireTargets = config.commonJS.dynamicRequireTargets || []; - // 如果一个模块被其他模块动态导入 - // 不对这个模块做任何处理 - if (dynamicRequireTargets.includes(src) || !config.commonJS.enable) { + + if (!config.commonJS.enable) { return; } this.ingorekeys = config.commonJS.ingoreKeys; - this.transform(this.ast, options); + this.transform(this.ast); + + if (dynamicRequireTargets.includes(src)) { + this.state.dynamicRequired = true; + return; + } if (this.state.isCJS) { - console.log('---------'); - console.log('cjsRequireModules', this.state.cjsRequireModules); - console.log('usedExports', this.state.usedExports); - console.log( + log('---------'); + log('cjsRequireModules', this.state.cjsRequireModules); + log('usedExports', this.state.usedExports); + log( 'isDynamicUsedExportsProperty', this.state.isDynamicUsedExportsProperty ); - console.log('isUsedExportsObject', this.state.isUsedExportsObject); - // console.log('cjsExportModules', this.state.cjsExportModules); - console.log('---------'); + log('isUsedExportsObject', this.state.isUsedExportsObject); + // log('cjsExportModules', this.state.cjsExportModules); + log('---------'); } } @@ -105,8 +99,6 @@ class TransformCommonJs { return; } - console.log(exportName); - Array.from(this.state.cjsExportModules).some(([name, cjsPath]) => { if (exportName === name) { cjsPath.remove(); @@ -115,18 +107,7 @@ class TransformCommonJs { }); } - markNodeDeep(node, flag) { - node[flag] = true; - traverse(node, { - noScope: true, - enter(path) { - let {node} = path; - node[flag] = true; - }, - }); - } - - transform(ast, options = {}) { + transform(ast) { let that = this; traverse(ast, { CallExpression: { @@ -141,6 +122,7 @@ class TransformCommonJs { let source = getStaticValue(node.arguments[0]); + // 动态导入 if (source === false) { console.warn( `Dynamic cjsRequireModules are not currently supported: ${path.toString()}. please configure dynamicrequiretargets` @@ -152,8 +134,9 @@ class TransformCommonJs { let {parentPath} = path; let {node: parentNode} = parentPath; - let requireNames = - this.state.cjsRequireModules.get(source); + let requireNames = this.state.cjsRequireModules.get( + source + ); if (!requireNames) { requireNames = new Set(); this.state.cjsRequireModules.set( @@ -162,7 +145,10 @@ class TransformCommonJs { ); } - // let {a} = require('a') + // 节点:let {a} = require('a') + // 可能存在的问题,require 的对象被其他函数包装后。例如: + // let {a} = fn(require('a')) + // 此时的 a 并不是原对象的 a 属性 let objectPatternPath = path.findParent((parent) => { return t.isObjectPattern(parent.node.id); }); @@ -188,8 +174,9 @@ class TransformCommonJs { requireNames.add(name); } else if (source) { - // require('./a') - // 声明语句才有:let a = require('./a') + // 节点是 require('./a') 的情况 + + // 声明语句:let a = require('./a') let declaratorParentPath = path.find((path) => { return t.isVariableDeclarator(path); }); @@ -200,6 +187,8 @@ class TransformCommonJs { ''; let usedNames = []; + // 只有是声明语句才去分析属性的使用情况 + // 例如:let a = require('./a'),去分析 a 上哪些属性被访问 if (name) { let binding = path.scope.getBinding(name); @@ -260,8 +249,9 @@ class TransformCommonJs { }) ); } else { - let id = - path.scope.generateUidIdentifier(exportName); + let id = path.scope.generateUidIdentifier( + exportName + ); let declaration = t.variableDeclaration('let', [ t.variableDeclarator(id, rightNode), ]); @@ -292,7 +282,8 @@ class TransformCommonJs { const moduleBinding = path.scope.getBinding('module'); const exportsBinding = path.scope.getBinding('exports'); - // module.exports.x = 1; 不包含子属性 module.exports.x.y = 1; + // 节点 module.exports.x = 1; + // 不包含访问子属性 module.exports.x.y = 1; if ( t.isMemberExpression(path.node.left.object) && path.node.left.object.object.name === 'module' @@ -307,7 +298,7 @@ class TransformCommonJs { ) { let name = getStaticMemberPro(path.node.left); - // 动态导出,不转换 + // 动态导出 if (name === false) { return; } @@ -316,20 +307,15 @@ class TransformCommonJs { return; } - this.state.isCJS = true; - generateExportNode(path, name); } } else if (path.node.left.object.name === 'exports') { - // exports.x = 1; 不包含子属性 exports.x.y = 1; + // 节点 exports.x = 1; + // 不包含访问子属性 exports.x.y = 1; let name = getStaticMemberPro(path.node.left); if ( exportsBinding || - // If export is named "default" leave as is. - // It is not possible to export "default" as a named export. - // e.g. `export.default = 'a'` - // 动态导出和默认导出,不转换 - name === 'default' || + // 动态导出 name === false ) { return; @@ -339,8 +325,6 @@ class TransformCommonJs { return; } - this.state.isCJS = true; - generateExportNode(path, name); } } @@ -385,7 +369,7 @@ class TransformCommonJs { return leftPath === path; }; - // module.exports.x + // 节点 module.exports.x if ( t.isMemberExpression(path.node.object) && path.node.object.object.name === 'module' @@ -394,6 +378,8 @@ class TransformCommonJs { return; } + this.state.isCJS = true; + if (checkIsAssignmentExpressionLeft()) { return; } @@ -402,9 +388,9 @@ class TransformCommonJs { path.node.object ); - // 动态访问了module上的属性 - // 无法确切的知道是否访问了exports属性 - // 进而无法知道访问了exports的哪些属性 + // 动态访问了 module 上的属性 + // 无法确切的知道是否访问了 exports 属性 + // 进而无法知道访问了exports 的哪些属性 if (staticModuleProVal === false) { this.state.isDynamicUsedExportsProperty = true; return; @@ -416,11 +402,13 @@ class TransformCommonJs { addUsedExports(); } else if (path.node.object.name === 'exports') { - // exports.x + // 节点 exports.x if (exportsBinding) { return; } + this.state.isCJS = true; + if (checkIsAssignmentExpressionLeft()) { return; } @@ -432,6 +420,8 @@ class TransformCommonJs { return; } + this.state.isCJS = true; + let staticModuleProVal = getStaticMemberPro(path.node); if (staticModuleProVal !== 'exports') { @@ -468,13 +458,16 @@ class TransformCommonJs { if ( // 是exports path.node.name === 'exports' && - // 父节点不是对象属性访问,例如:module.exports + // 父节点不是对象属性访问,例如:module.exports 或者 exports.a !t.isMemberExpression(path.parentPath) && // 作用域无 binding exports - !path.scope.getBinding('exports') && - that.checkUsed(path) + !path.scope.getBinding('exports') ) { - this.state.isUsedExportsObject = true; + this.state.isCJS = true; + + if (that.checkUsed(path)) { + this.state.isUsedExportsObject = true; + } } }, }, @@ -511,31 +504,26 @@ class TransformCommonJs { return false; } + // Object.defineProperty(exports, "__esModule", { + // value: true + // }); + // 特殊处理,不算对 exports 整体的使用 + if (t.isCallExpression(parentPath)) { + let nextParam = path.getAllNextSiblings()[0]; + + let defineEsModule = + t.isStringLiteral(nextParam) && + nextParam.node.value === '__esModule'; + + if (defineEsModule) { + return false; + } + } + return true; } } module.exports = { - TransformCommonJs, + CommonJS, }; - -// let src = path.resolve(__dirname, './transform-test.js'); -// let code = readFile(src); - -// console.time('transform'); -// let tt = new TransformCommonJs({src, code}); -// console.timeEnd('transform'); - -// const {code: outputCode} = generate( -// tt.ast, -// { -// /* options */ -// decoratorsBeforeExport: true, -// }, -// code -// ); - -// writeFile( -// path.resolve(path.resolve(__dirname, './transform-test-a.js')), -// outputCode -// ); diff --git a/packages/wxa-cli/src/tree-shake/tree-shake.js b/packages/wxa-cli/src/tree-shake/tree-shake.js new file mode 100644 index 00000000..89d454a1 --- /dev/null +++ b/packages/wxa-cli/src/tree-shake/tree-shake.js @@ -0,0 +1,441 @@ +const {dceDeclaration, log} = require('./util'); +const generate = require('@babel/generator').default; + +class TreeShake { + // 根文件集 + roots = []; + // 由 impoet->export 组成的链 + chains = {}; + // 没有被 import 的 export 节点集合 + noReferencedExports = []; + constructor(roots) { + this.roots = roots; + } + + run() { + this.roots.forEach((root) => { + this.shake(root); + }); + + log('shook'); + + this.roots.forEach((root) => { + this.collectNotReferencedExports(root); + }); + + log('collected'); + + this.remove(); + + log('removed'); + + let contents = {}; + this.roots.forEach((root) => { + contents = {...contents, ...this.output(root)}; + }); + + log('output'); + return contents; + } + + shake(dep) { + if (dep._shook) { + return; + } + + let {imports, exports, isRoot, src: depSrc} = dep; + + log('shake src', depSrc); + + let fileExportChain = []; + this.chains[depSrc] = fileExportChain; + + // 从 import 语句开始,构建一条 import->export->export 链式关系 + let collectExportChain = (dep, childSrc, currentChain) => { + if (currentChain.length) { + let child = dep.children.find( + (child) => child.src === childSrc + ); + let exportsArray = Object.entries(child.exports); + let localIndex = exportsArray.findIndex( + ([src]) => src == child.src + ); + let localExports = null; + let externalExports = [...exportsArray]; + + if (localIndex !== -1) { + localExports = externalExports.splice(localIndex, 1)[0]; + } + + let usedExports = {}; + let nextChain = []; + + let setCurrentChain = (chainNode, childName, path) => { + let childChainNode = { + name: childName, + path, + children: [], + parent: chainNode, + dep: child, + }; + chainNode.children.push(childChainNode); + nextChain.push(childChainNode); + path.$chain = { + [childName]: childChainNode, + }; + }; + + let getExportLocalName = (path, defaultName) => { + // 兼容 exports.x = 1 节点 + if (path.$isCjsExport) { + return defaultName; + } + + let local = path.node.local; + if (local) { + return local.name; + } + + return '*'; + }; + + let addUsedExport = (src, name, path) => { + usedExports[src] = usedExports[src] || {}; + + if (name) { + usedExports[src][name] = path; + } + }; + + let collect = (chainNode, path, src, defaultLocalName) => { + let localName = ''; + + if (defaultLocalName) { + localName = defaultLocalName; + } else { + localName = getExportLocalName(path); + } + + // 对于导出其他文件模块的语句:export {a as aa} from '' + // 可以理解为通过这条语句到对应文件去寻找 a 模块 + // 如果多次解析到这条语句,并且寻找的模块名一样,那每次后面的分析都是一样的 + // 一般来说 export {a as aa} from '' 语句寻找的就是语句中定义的模块 a + // 但 export * from '',寻找的模块名可能由父节点决定 + if (path.$chain && path.$chain[localName]) { + chainNode.children.push(path.$chain[localName]); + return; + } + + setCurrentChain(chainNode, localName, path); + addUsedExport(src, localName, path); + }; + + let importAllChainNode = currentChain.find( + (node) => node.name === '*' + ); + + if (importAllChainNode) { + let importDefaultChainNode = currentChain.find( + (node) => node.name === 'default' + ); + + let markedDefalut = false; + if (localExports) { + Object.entries(localExports[1]).forEach( + ([name, path]) => { + if (name === 'default') { + if (importDefaultChainNode) { + markedDefalut = true; + setCurrentChain( + importDefaultChainNode, + 'dafault', + path + ); + } + } else { + let localName = getExportLocalName( + path, + name + ); + setCurrentChain( + importAllChainNode, + localName, + path + ); + } + } + ); + } + + externalExports.forEach(([src, exportInfo]) => { + Object.entries(exportInfo).forEach(([name, path]) => { + if ( + name === 'default' && + importDefaultChainNode && + !markedDefalut + ) { + collect(importDefaultChainNode, path, src); + } else if (name !== 'default') { + collect(importAllChainNode, path, src); + } + }); + }); + } else { + currentChain.forEach((chainNode) => { + let name = chainNode.name; + if (localExports) { + let path = localExports[1][name]; + + if (path) { + if (name === 'default') { + setCurrentChain(chainNode, 'dafault', path); + } else { + let localName = getExportLocalName( + path, + name + ); + setCurrentChain(chainNode, localName, path); + } + return; + } + } + + externalExports.forEach(([src, exportInfo]) => { + let path = exportInfo[name]; + + if (path) { + collect(chainNode, path, src); + } + + path = exportInfo['*']; + + if (path) { + collect(chainNode, path, src, name); + } + }); + }); + } + + Object.entries(usedExports).forEach((src, value) => { + let childUsedNames = Object.keys(value); + let childChain = childUsedNames.map((n) => { + return nextChain.find( + (chainNode) => chainNode.name === n + ); + }); + + collectExportChain(child, src, childChain); + }); + } + }; + + Object.entries(imports).forEach(([src, value]) => { + let currentChain = []; + + Object.entries(value).forEach(([name, path]) => { + let chainNode = { + parent: null, + name, + path, + children: [], + dep, + }; + fileExportChain.push(chainNode); + currentChain.push(chainNode); + }); + + collectExportChain(dep, src, currentChain); + }); + + // 根节点的 export 语句默认全部保留 + // 所以还需要处理根节点的 export 语句(export {} from '') + if (isRoot) { + Object.entries(exports).forEach(([src, exportInfo]) => { + if (src !== dep.src) { + let currentChain = []; + + Object.entries(exportInfo).forEach(([name, path]) => { + let chainNode = { + parent: null, + name, + path, + children: [], + dep, + }; + fileExportChain.push(chainNode); + currentChain.push(chainNode); + }); + + collectExportChain(dep, src, currentChain); + } + }); + } + + let markExport = () => { + let visitedChainNodes = []; + + let findLastChainNode = (chainNode) => { + // 某个节点在链上出现过两次,这条链不会找到最终导出的模块 + if (visitedChainNodes.includes(chainNode)) { + return; + } + + visitedChainNodes.push(chainNode); + + if (!chainNode.children.length) { + let exportPath = chainNode.path; + + // 最后一个节点是文件内导出(不是 export a from '') + // 才算是找到最终导出的节点 + if (exportPath.node && !exportPath.node.source) { + visitedChainNodes.forEach((visitedNode, index) => { + // 第一个节点是 import 节点或者 root 的 export 节点 + // 跳过 + if (index === 0) { + return; + } + + let {path} = visitedNode; + + // 这条链上的所有 export 节点的 $extReferences 属性添加 import 节点 + // 表示它们被导入过 + path.$extReferences.add(visitedChainNodes[0].path); + }); + } + } else { + chainNode.children.forEach((child) => { + findLastChainNode(child); + }); + } + + visitedChainNodes.pop(); + }; + + fileExportChain.forEach((chainNode) => { + findLastChainNode(chainNode); + }); + }; + + markExport(); + + dep._shook = true; + dep.children.forEach((child) => this.shake(child)); + } + + // 收集没有被导入过的 export 节点 + collectNotReferencedExports(dep) { + if (dep._colletced) { + return; + } + + let {exports, src} = dep; + + log('collect src', src); + + Object.entries(exports).forEach(([src, value]) => { + Object.entries(value).forEach(([name, path]) => { + if (!path.$extReferences.size) { + this.noReferencedExports.push({path, dep, name}); + } + }); + }); + + dep._colletced = true; + + dep.children.forEach((child) => + this.collectNotReferencedExports(child) + ); + } + + remove() { + let visitedChainNodes = []; + let removeExtReference = (chainNode, importPath) => { + // 循环依赖 + if (visitedChainNodes.includes(chainNode)) { + return; + } + + visitedChainNodes.push(chainNode); + chainNode.children.forEach((childNode) => { + childNode.path.$extReferences.delete(importPath); + + if (childNode.path.$extReferences.size === 0) { + this.noReferencedExports.push({ + path: childNode.path, + dep: childNode.dep, + name: childNode.name, + }); + } + + removeExtReference(childNode, importPath); + }); + visitedChainNodes.pop(); + }; + + for (let i = 0; i < this.noReferencedExports.length; i++) { + const {path: exportPath, dep, name} = this.noReferencedExports[i]; + let {commonjs, topScope, src} = dep; + + if (exportPath.$isCjsExport) { + log(src, name); + commonjs.deleteCJSExport(name); + } else { + log(src, name); + exportPath.remove(); + } + + let importPaths = dceDeclaration(topScope); + // 如果删除了 import 节点 + // 对应链上的所有 export 节点都删除这个 import 节点 + if (importPaths.length) { + let chain = this.chains[src]; + + importPaths.forEach((importPath) => { + let chainNode = chain.find( + (chainNode) => chainNode.path === importPath + ); + + removeExtReference(chainNode, importPath); + }); + } + } + } + + output(dep) { + let contents = {}; + + let run = (dep) => { + let {ast, code, src} = dep; + + if (dep._output) { + return; + } + + const {code: outputCode} = generate( + ast, + { + decoratorsBeforeExport: true, + }, + code + ); + + contents[src] = { + code, + formattedCode: outputCode, + src, + }; + + dep._output = true; + + dep.children.forEach((child) => { + run(child); + }); + }; + + run(dep); + + return contents; + } +} + +module.exports = {TreeShake}; diff --git a/packages/wxa-cli/src/tree-shake/util.js b/packages/wxa-cli/src/tree-shake/util.js index ad64f99a..9711ea67 100644 --- a/packages/wxa-cli/src/tree-shake/util.js +++ b/packages/wxa-cli/src/tree-shake/util.js @@ -32,7 +32,6 @@ function isFile(p) { } function isDir(p) { - // console.log(isDir, fs.existsSync(p), p); if (!fs.existsSync(p)) { return false; } @@ -54,14 +53,28 @@ function getPkgConfig(npmSrc, lib) { } /** - * import路径: - * "./a", "a", "@/a", "/a" - * + * + * @description 将import路径解析为绝对路径 + * @example + * resolveDepSrc({ + fileSrc: path.join(process.cwd(), './src/a.js'), + depSrc: '@/b', + root: 'src', + alias: { + '@': path.join(process.cwd(), '/src/xxx'), + }, + }) + * @param {string} fileSrc 文件路径 + * @param {string} depSrc impot 引入的路径("./a", "a", "@/a", "/a") + * @param {string} root depsrc 为绝对路径(例如:/a)时相对的目录 + * @param {string} alias 路径别名,例如:{'@': 'src'} + * @param {string} npm npm 目录,例如:node_modules + * @return {string} 依赖的绝对路径 */ - -let cwd = process.cwd(); function resolveDepSrc({fileSrc, depSrc, root, alias, npm}) { - let getDepAbsoulte = (src) => { + let cwd = process.cwd(); + + let getFileSrc = (src) => { if (isDir(src)) { return path.join(src, 'index.js'); } @@ -90,17 +103,17 @@ function resolveDepSrc({fileSrc, depSrc, root, alias, npm}) { }); if (matched) { - return getDepAbsoulte(absoluteSrc); + return getFileSrc(absoluteSrc); } } if (depSrc.startsWith('/')) { - return getDepAbsoulte(path.resolve(cwd, root, depSrc.replace('/', ''))); + return getFileSrc(path.resolve(cwd, root, depSrc.replace('/', ''))); } if (depSrc.startsWith('./') || depSrc.startsWith('../')) { let fileDir = path.dirname(fileSrc); - return getDepAbsoulte(path.resolve(fileDir, depSrc)); + return getFileSrc(path.resolve(fileDir, depSrc)); } let npmSrc = path.join(cwd, npm); @@ -126,7 +139,7 @@ function resolveDepSrc({fileSrc, depSrc, root, alias, npm}) { main = pkg.browser; } - return getDepAbsoulte(path.join(npmSrc, depSrc, main)); + return getFileSrc(path.join(npmSrc, depSrc, main)); } function parseESCode(code) { @@ -154,6 +167,7 @@ function isChildNode(parent, child) { return is; } +// 删除 scope 下未引用的 binding function dceDeclaration(scope) { let importPaths = []; @@ -253,9 +267,18 @@ function dceDeclaration(scope) { if ( // 过滤 let [zz, xx, cc] = [1, 2, 3]; // 变量声明语句可能有副作用,不能简单去除 - // 例如:let a = obj.x,obj.x 可能有访问器属性。其他连等情况等等 - // (t.isVariableDeclarator(bindingPath) && - // !t.isArrayPattern(bindingPath.node.id)) || + // 例如: + // let a = obj.x,obj.x 可能有访问器属性。 + // let a = b = 1 连等 + // let a = fn() 非纯函数运行 + // 先处理为 init 为 identifier、函数、class、Literals 时,可以删除 + (t.isVariableDeclarator(bindingPath) && + !t.isArrayPattern(bindingPath.node.id) && + (t.isIdentifier(bindingPath.node.init) || + t.isLiteral(bindingPath.node.init) || + t.isArrowFunctionExpression(bindingPath.node.init) || + t.isFunctionExpression(bindingPath.node.init) || + t.isClassExpression(bindingPath.node.init))) || t.isClassDeclaration(bindingPath) || t.isFunctionDeclaration(bindingPath) || t.isImportDefaultSpecifier(bindingPath) || @@ -278,21 +301,14 @@ function dceDeclaration(scope) { return importPaths; } -// console.log( -// resolveDepSrc({ -// fileSrc: path.join(cwd, './src/a.js'), -// depSrc: '@/b', -// root: 'src', -// alias: { -// '@': path.join(cwd, '/src/xxx'), -// }, -// }) -// ); - function unique(ary) { return [...new Set(ary)]; } +function log(...params) { + config.debug && log(...params); +} + module.exports = { readFile, writeFile, @@ -301,4 +317,5 @@ module.exports = { dceDeclaration, isChildNode, unique, + log, }; From cb1cef0f5fbbc492d338209d8dda2d0ed41f5489 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Wed, 14 Jul 2021 19:29:30 +0800 Subject: [PATCH 14/20] =?UTF-8?q?feat:=20=E5=88=A0=E9=99=A4=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/example/cjs1.js | 119 -------------------- packages/wxa-cli/example/cjs2.js | 25 ----- packages/wxa-cli/example/expDFOF/a.js | 13 --- packages/wxa-cli/example/expDFOF/index.js | 27 ----- packages/wxa-cli/example/index.js | 131 ---------------------- packages/wxa-cli/example/shaking/cjs1.js | 30 ----- packages/wxa-cli/example/shaking/cjs2.js | 3 - packages/wxa-cli/example/shaking/index.js | 124 -------------------- packages/wxa-cli/example/shaking/user.js | 13 --- packages/wxa-cli/example/shaking/user2.js | 2 - packages/wxa-cli/example/test.js | 58 ---------- packages/wxa-cli/example/user.js | 19 ---- packages/wxa-cli/example/user2.js | 8 -- packages/wxa-cli/src/tree-shake/index.js | 17 --- packages/wxa-cli/src/tree-shake/scope.js | 53 --------- packages/wxa-cli/src/tree-shake/test.js | 25 ----- 16 files changed, 667 deletions(-) delete mode 100644 packages/wxa-cli/example/cjs1.js delete mode 100644 packages/wxa-cli/example/cjs2.js delete mode 100644 packages/wxa-cli/example/expDFOF/a.js delete mode 100644 packages/wxa-cli/example/expDFOF/index.js delete mode 100644 packages/wxa-cli/example/index.js delete mode 100644 packages/wxa-cli/example/shaking/cjs1.js delete mode 100644 packages/wxa-cli/example/shaking/cjs2.js delete mode 100644 packages/wxa-cli/example/shaking/index.js delete mode 100644 packages/wxa-cli/example/shaking/user.js delete mode 100644 packages/wxa-cli/example/shaking/user2.js delete mode 100644 packages/wxa-cli/example/test.js delete mode 100644 packages/wxa-cli/example/user.js delete mode 100644 packages/wxa-cli/example/user2.js delete mode 100644 packages/wxa-cli/src/tree-shake/scope.js delete mode 100644 packages/wxa-cli/src/tree-shake/test.js diff --git a/packages/wxa-cli/example/cjs1.js b/packages/wxa-cli/example/cjs1.js deleted file mode 100644 index f2fbbafe..00000000 --- a/packages/wxa-cli/example/cjs1.js +++ /dev/null @@ -1,119 +0,0 @@ -let fn1 = require('./cjs2').fn1; - -fn1(); - -// Object.defineProperty(exports, '__esModule', { -// value: true, -// }); -exports.getFiles = getFiles; -// exports.getConfig = getConfig; -module.exports.readFile = readFile; -exports.writeFile = writeFile; -exports.isFile = isFile; -exports.isDir = isDir; -exports.getRelative = getRelative; -exports.getDistPath = getDistPath; -exports.copy = copy; -exports.amazingCache = amazingCache; -exports.applyPlugins = applyPlugins; -exports.isEmpty = isEmpty; -exports.getHash = getHash; -exports.getHashWithString = getHashWithString; -exports.promiseSerial = promiseSerial; -exports.getClassSet = getClassSet; -exports.addClass = addClass; -exports.removeClass = removeClass; - -module.exports = {getFiles}; - -function getFiles(dir = process.cwd(), prefix = '') { - let rst = []; - - exports.rst = rst; - - let aaaa = 'aaa'; - // exports[aaaa] = aaaa; - - // let ttt= require('sss'); - - // console.log(ttt); - - // exports.addClass; - // module.exports.removeClass; - // exports[rst]; -} - -// function getConfig() { -// let configPath = _path.default.join(process.cwd(), 'wxa.config.js'); - -// let config = require(configPath); - -// return config; -// } - -function readFile(p) {} - -function writeFile(p, data) {} - -function isFile(p) {} - -function isDir(p) {} - -function getRelative(opath) {} - -function getDistPath(opath, ext, src, dist) {} - -function copy(from, to) {} - -function amazingCache(params, needCache) {} - -function applyPlugins(plugins, compiler) { - if (plugins == null) return; // console.log(plugins); - - if (typeof plugins !== 'object') { - throw new Error('wxa配置文件有误,plugins'); - } - if (!Array.isArray(plugins)) plugins = [plugins]; - plugins.forEach((plugin) => plugin.apply(compiler)); -} - -function isEmpty(n) { - return n == null || n === ''; -} - -function getHash(filepath) {} - -function getHashWithString(content) {} - -function promiseSerial(funs) { - return funs.reduce((promise, fun) => { - return promise.then((result) => - fun().then(Array.prototype.concat.bind(result)) - ); - }, Promise.resolve([])); -} - -function getClassSet(classStr) { - let classList = []; - - if (classStr && typeof classStr === 'string') { - classList = classStr.split(' '); - } - - return new Set(classList); -} - -function addClass(classStr, newClass) { - let classSet = getClassSet(classStr); - classSet.add(newClass); - return Array.from(classSet); -} - -function removeClass(classStr, destClass) { - let classSet = getClassSet(classStr); - classSet.delete(destClass); - return Array.from(classSet); -} -// # sourceMappingURL=utils.js.map - -exports.a = function m() {}; diff --git a/packages/wxa-cli/example/cjs2.js b/packages/wxa-cli/example/cjs2.js deleted file mode 100644 index 9fc85ea2..00000000 --- a/packages/wxa-cli/example/cjs2.js +++ /dev/null @@ -1,25 +0,0 @@ - - -function fn1(params) { - -} - - -function fn2(params) { - -} - - -function fn3(params) { - -} - - -exports.fn1 = fn1; -exports.fn2 = fn2; -exports.fn3 = fn3; - - -exports.fn4 = function fn4() { - -}; diff --git a/packages/wxa-cli/example/expDFOF/a.js b/packages/wxa-cli/example/expDFOF/a.js deleted file mode 100644 index 23a0ce7e..00000000 --- a/packages/wxa-cli/example/expDFOF/a.js +++ /dev/null @@ -1,13 +0,0 @@ -let num1 = 1; -let num2 = 2; -let obj1 ={ - x: 1, -}; - -function name(params) { - -} - -export default { - -}; diff --git a/packages/wxa-cli/example/expDFOF/index.js b/packages/wxa-cli/example/expDFOF/index.js deleted file mode 100644 index 6be76333..00000000 --- a/packages/wxa-cli/example/expDFOF/index.js +++ /dev/null @@ -1,27 +0,0 @@ - - -export {default} from './a'; - - -/* eslint-disable one-var */ -// 具名导出 -export {a as aa, b, c} from ''; -export * as all from ''; -export function fn1() {} -let o1 = 1, o2=3; -export {o1 as o11, o2}; - -// 默认导出 -// export {default} from '' -// export {a as default} from '' -// export * as default from '' -// export {a as default} -// let p1 = 1 -// export default p1 -// export default 1 -// export default a=1 -// export default function() {} -// export default {} - -// 导出全部 -export * from ''; diff --git a/packages/wxa-cli/example/index.js b/packages/wxa-cli/example/index.js deleted file mode 100644 index abf3bdb1..00000000 --- a/packages/wxa-cli/example/index.js +++ /dev/null @@ -1,131 +0,0 @@ -/* eslint-disable one-var */ -import getAge, {getName as getMyName} from './user'; -import * as user from './user'; -import {getName as tttqw} from './user'; - -import {writeFile, isFile} from './cjs1'; - -writeFile(); -isFile(); - -getName(); - -let ssqqww =1; - -// console.log(user); -console.log(getAge); - -let a = {x: 1}, - n = 1; -let t = 10; -function m(x = 1, y) { - a = 5; - ++a; - t = 9; - t + 5; - let qqq = 10; - let ssqqww =5; - console.log(ssqqww); -} -m(); - -try { - let a = 1; - console.log(a); -} catch (error) { - -} - -let ttt = function({x: xxx, y}) {}; - -let sss = (a, b) => {}; - -[1, 2, 3].forEach(function(item) {}); - - -for (i = 0; i < 100; i++) {} - -class Myclass { - [n] = 1; - [n] = () => {}; -} - -let [zz, xx, cc] = [1, 2, 3]; -let {x: x1} = {x: 1, y2: 2}; - -let {detail: {code, code1}} = {detail: {code: 1}}; - - -let o22=1; -let o11 = o22 =3; - -console.log(o22); - - -let clearErrorMsg = function({p1, p2}, {currentTarget: {dataset: {rule, as, name, opts={}}}}, [asq, ttqw], ppp) { - let asdf='p'; -}; - - -function aaa({p1, p2}) { - let asdwqe='p'; - - function att() { - - } -}; - -aaa(); - - -clearErrorMsg(); - - -mm(); - -function name(params) { - let t = {q: 1}; - let q = 2; - q++; - t.q; -} - - -function aaas() { - name(); -} - -let obj = { - x: 1, - t() {}, -}; - -(function(x, y) {})(); - -// export default { -// x: 1, -// t() { -// }, -// m, -// age, -// }; - -export let qwe=1, rty=2; -export function getName() {} -export function mm() {} - -// export {m as qqqqq, a as default}; - -// export {x, y} from './a'; - -export default class asf {}; - -export {Myclass}; -// eslint-disable-next-line no-var - -export {mm as ttttttt}; - -// export {getName as tttt} from './user'; -// export {default} from './user'; - -// export * as tttttt from './user'; diff --git a/packages/wxa-cli/example/shaking/cjs1.js b/packages/wxa-cli/example/shaking/cjs1.js deleted file mode 100644 index 0bb3741a..00000000 --- a/packages/wxa-cli/example/shaking/cjs1.js +++ /dev/null @@ -1,30 +0,0 @@ -let fn1 = require('./cjs2').fn1; - -fn1(); // Object.defineProperty(exports, '__esModule', { -// value: true, -// }); - -exports.writeFile = writeFile; -exports.isFile = isFile; -module.exports = { - getFiles -}; - -function getFiles(dir = process.cwd(), prefix = '') { - let rst = []; - exports.rst = rst; // exports[aaaa] = aaaa; - // let ttt= require('sss'); - // console.log(ttt); - // exports.addClass; - // module.exports.removeClass; - // exports[rst]; -} // function getConfig() { -// let configPath = _path.default.join(process.cwd(), 'wxa.config.js'); -// let config = require(configPath); -// return config; -// } - - -function writeFile(p, data) {} - -function isFile(p) {} \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/cjs2.js b/packages/wxa-cli/example/shaking/cjs2.js deleted file mode 100644 index f6a7929f..00000000 --- a/packages/wxa-cli/example/shaking/cjs2.js +++ /dev/null @@ -1,3 +0,0 @@ -function fn1(params) {} - -exports.fn1 = fn1; \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/index.js b/packages/wxa-cli/example/shaking/index.js deleted file mode 100644 index 1e3e28b4..00000000 --- a/packages/wxa-cli/example/shaking/index.js +++ /dev/null @@ -1,124 +0,0 @@ -/* eslint-disable one-var */ -import getAge from './user'; -import './user'; -import './user'; -import { writeFile, isFile } from './cjs1'; -writeFile(); -isFile(); -getName(); -// console.log(user); -console.log(getAge); -let a = { - x: 1 -}, - n = 1; -let t = 10; - -function m(x = 1, y) { - a = 5; - ++a; - t = 9; - t + 5; - let ssqqww = 5; - console.log(ssqqww); -} - -m(); - -try { - let a = 1; - console.log(a); -} catch (error) {} - -[1, 2, 3].forEach(function (item) {}); - -for (i = 0; i < 100; i++) {} - -class Myclass { - [n] = 1; - [n] = () => {}; -} - -let [zz, xx, cc] = [1, 2, 3]; -let { - x: x1 -} = { - x: 1, - y2: 2 -}; -let { - detail: { - code, - code1 - } -} = { - detail: { - code: 1 - } -}; -let o22 = 1; -let o11 = o22 = 3; -console.log(o22); - -let clearErrorMsg = function ({ - p1, - p2 -}, { - currentTarget: { - dataset: { - rule, - as, - name, - opts = {} - } - } -}, [asq, ttqw], ppp) {}; - -function aaa({ - p1, - p2 -}) {} - -; -aaa(); -clearErrorMsg(); -mm(); -let obj = { - x: 1, - - t() {} - -}; - -(function (x, y) {})(); // export default { -// x: 1, -// t() { -// }, -// m, -// age, -// }; - - -let qwe = 1, - rty = 2; -export { qwe, rty }; - -function getName() {} - -export { getName }; - -function mm() {} - -export { mm }; - -class asf {} - -// export {m as qqqqq, a as default}; -// export {x, y} from './a'; -export default asf; -; -export { Myclass }; // eslint-disable-next-line no-var - -export { mm as ttttttt }; // export {getName as tttt} from './user'; -// export {default} from './user'; -// export * as tttttt from './user'; \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/user.js b/packages/wxa-cli/example/shaking/user.js deleted file mode 100644 index dce4848e..00000000 --- a/packages/wxa-cli/example/shaking/user.js +++ /dev/null @@ -1,13 +0,0 @@ -import './user2'; -export {}; - -function getAge(params) {} - -export default getAge; // let a =1; -// export default a; -// eslint-disable-next-line one-var - -export {}; -export {}; -export {}; -export {} from './user2'; \ No newline at end of file diff --git a/packages/wxa-cli/example/shaking/user2.js b/packages/wxa-cli/example/shaking/user2.js deleted file mode 100644 index f4e5405f..00000000 --- a/packages/wxa-cli/example/shaking/user2.js +++ /dev/null @@ -1,2 +0,0 @@ -export {}; -export {}; \ No newline at end of file diff --git a/packages/wxa-cli/example/test.js b/packages/wxa-cli/example/test.js deleted file mode 100644 index d88b550f..00000000 --- a/packages/wxa-cli/example/test.js +++ /dev/null @@ -1,58 +0,0 @@ -/* eslint-disable one-var */ - -let obj = {x: 1}, - num1 = 1; -let num2 = 10; -let str1 = 'a'; -function m() { - num1 = 5; - ++num2; - let qqq = 10; -} - -m(); - -let fn1 = function() {}; - -let fn2 = () => {}; - -[1, 2, 3].forEach(function(item) {}); - -for (i = 0; i < 100; i++) {} - -class Myclass { - [str1] = 1; - [str1] = () => {}; -} - - -m(); - -function name(params) { - let t = {q: 1}; - let q = 2; - q++; - t.q; -} - - -(function(x, y) {})(); - -getName(); -// export default { -// x: 1, -// t() { -// }, -// m, -// age, -// }; -export * from './user'; -export function getName() {} -// export {m as qqqqq, a as default}; - -// export {x, y} from './a'; - -export default function() {} - -export {Myclass}; -// eslint-disable-next-line no-var diff --git a/packages/wxa-cli/example/user.js b/packages/wxa-cli/example/user.js deleted file mode 100644 index fd96d1ef..00000000 --- a/packages/wxa-cli/example/user.js +++ /dev/null @@ -1,19 +0,0 @@ -import {fn1 as fn11} from './user2'; - -export function getName() {} - -export default function getAge(params) {} - -// let a =1; -// export default a; - -// eslint-disable-next-line one-var -export let mm1 = 1, - c = function mm2(params) {}; - -function fn2(params) {} - -export {fn2}; -export {fn11}; - -export {fn2 as fn22} from './user2'; diff --git a/packages/wxa-cli/example/user2.js b/packages/wxa-cli/example/user2.js deleted file mode 100644 index 3d3f9131..00000000 --- a/packages/wxa-cli/example/user2.js +++ /dev/null @@ -1,8 +0,0 @@ -export function fn1() { - -} - -export function fn2() { - -} - diff --git a/packages/wxa-cli/src/tree-shake/index.js b/packages/wxa-cli/src/tree-shake/index.js index 69e13006..acf7c7f7 100644 --- a/packages/wxa-cli/src/tree-shake/index.js +++ b/packages/wxa-cli/src/tree-shake/index.js @@ -32,20 +32,3 @@ function treeShake(options = {}) { module.exports = { treeShake, }; - -// console.time('end'); -// let path = require('path'); -// const {writeFile} = require('./util'); -// let entrySrc = path.resolve(__dirname, '../../example/index.js'); -// let files = treeShake({ -// entry: [{src: entrySrc}], -// commonJS: {enable: true}, -// }); - -// Object.values(files).forEach(({src, formattedCode}) => { -// writeFile( -// path.resolve(path.dirname(src), './shaking', path.basename(src)), -// formattedCode -// ); -// }); -// console.timeEnd('end'); diff --git a/packages/wxa-cli/src/tree-shake/scope.js b/packages/wxa-cli/src/tree-shake/scope.js deleted file mode 100644 index 3ab6c0df..00000000 --- a/packages/wxa-cli/src/tree-shake/scope.js +++ /dev/null @@ -1,53 +0,0 @@ -class Scope { - constructor(options) { - options = options || {}; - - this.parent = options.parent; - this.depth = this.parent ? this.parent.depth + 1 : 0; - this.names = options.params || []; - this.nodes = {}; - this.isBlockScope = !!options.block; - this.children = []; - - if (this.parent) { - this.parent.children.push(this); - } - } - // 添加变量名 - // isBlockDeclaration 是否是块级声明:let const class import - add(node, name, isBlockDeclaration) { - if (!isBlockDeclaration && this.isBlockScope) { - // it's a `var` or function declaration, and this - // is a block scope, so we need to go up - this.parent.add(node, name, isBlockDeclaration); - } else { - this.names.push(name); - // 变量名可能重复,两个var声明同一变量 - if (this.nodes[name]) { - this.nodes[name].push(node); - } else { - this.nodes[name] = [node]; - } - } - } - - contains(name) { - return !!this.findDefiningScope(name); - } - - findDefiningScope(name) { - if (this.names.includes(name)) { - return this; - } - - if (this.parent) { - return this.parent.findDefiningScope(name); - } - - return null; - } -} - -module.exports = { - Scope, -}; diff --git a/packages/wxa-cli/src/tree-shake/test.js b/packages/wxa-cli/src/tree-shake/test.js deleted file mode 100644 index e1a47575..00000000 --- a/packages/wxa-cli/src/tree-shake/test.js +++ /dev/null @@ -1,25 +0,0 @@ -const generate = require('@babel/generator').default; -const traverse = require('@babel/traverse').default; -const {parse} = require('@babel/parser'); -let code = ``; - -code = ` -let a = require('/a'); - -a.x; -a.y; -a.default.u - -let n ='n'; -a[n]; - -let b = a;`; - -let ast = parse(code, {sourceType: 'unambiguous'}); -traverse(ast, { - enter(path) { - let scope = path.scope; - console.log(path.scope); - }, -}); - From 26d2169cf2ff623afe8db8186075b713269db0ea Mon Sep 17 00:00:00 2001 From: sparklinm Date: Wed, 14 Jul 2021 19:57:57 +0800 Subject: [PATCH 15/20] =?UTF-8?q?fix:=20=E5=88=A0=E9=99=A4=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/package.json | 2 -- packages/wxa-cli/src/my.html | 18 ------------------ 2 files changed, 20 deletions(-) delete mode 100644 packages/wxa-cli/src/my.html diff --git a/packages/wxa-cli/package.json b/packages/wxa-cli/package.json index c5f59bc4..dab15fbc 100644 --- a/packages/wxa-cli/package.json +++ b/packages/wxa-cli/package.json @@ -30,7 +30,6 @@ "babel-eslint": "^9.0.0", "eslint": "^4.15.0", "eslint-config-google": "^0.9.1", - "reserved-words": "^0.1.2", "semver": "^5.5.0", "webpack": "^4.28.3", "webpack-cli": "^3.2.0" @@ -70,7 +69,6 @@ "promise.prototype.finally": "^3.1.0", "shelljs": "^0.8.3", "tapable": "^1.0.0", - "valid-url": "^1.0.9", "lodash": "^4.17.21" }, "publishConfig": { diff --git a/packages/wxa-cli/src/my.html b/packages/wxa-cli/src/my.html deleted file mode 100644 index ae101b94..00000000 --- a/packages/wxa-cli/src/my.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - From 812e16ae7827fd9fcd634a2471036f75a5e6e8e0 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Thu, 15 Jul 2021 10:05:30 +0800 Subject: [PATCH 16/20] =?UTF-8?q?fix:=20=E8=BF=98=E5=8E=9Fpackage-lock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/package-lock.json | 344 ++++++++++++++--------------- 1 file changed, 169 insertions(+), 175 deletions(-) diff --git a/packages/wxa-cli/package-lock.json b/packages/wxa-cli/package-lock.json index 9cd6a8b9..e4b1b000 100644 --- a/packages/wxa-cli/package-lock.json +++ b/packages/wxa-cli/package-lock.json @@ -1738,9 +1738,9 @@ } }, "@wxa/compiler-babel": { - "version": "2.2.7", - "resolved": "https://registry.npm.taobao.org/@wxa/compiler-babel/download/@wxa/compiler-babel-2.2.7.tgz", - "integrity": "sha1-AydEuIAI8egJUNztqnDHmOEIXrA=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@wxa/compiler-babel/-/compiler-babel-2.2.0.tgz", + "integrity": "sha512-kjQL/T0vLdulAoaCVzlmAE3UbtC1e/c6JVmf/OL9hi7oDspAhlyHSySOH9JhTGYzOKPYbJpBrO1EoMMsnLWRMA==", "requires": { "@babel/core": "^7.1.0", "debug": "^4.0.1", @@ -1750,17 +1750,17 @@ }, "dependencies": { "debug": { - "version": "4.3.1", - "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.3.1.tgz?cache=0&sync_timestamp=1607566533140&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.3.1.tgz", - "integrity": "sha1-8NIpxQXgxtjEmsVT0bE9wYP2su4=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "requires": { - "ms": "2.1.2" + "ms": "^2.1.1" } }, "find-cache-dir": { "version": "2.1.0", - "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-2.1.0.tgz", - "integrity": "sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc=", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "requires": { "commondir": "^1.0.1", "make-dir": "^2.0.0", @@ -1770,11 +1770,11 @@ } }, "@wxa/compiler-sass": { - "version": "2.2.7", - "resolved": "https://registry.nlark.com/@wxa/compiler-sass/download/@wxa/compiler-sass-2.2.7.tgz", - "integrity": "sha1-gGe1vzRPRFW0Yg95snOOqAePa1E=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@wxa/compiler-sass/-/compiler-sass-2.2.0.tgz", + "integrity": "sha512-te92dBDbVQDMaqaTopmK9pIx8W2WWg3bESVv4T71WS4UHLzy3boqnjICS5w4ZfCHpeL4imvMiAVZe37tHcT3Jw==", "requires": { - "node-sass": "^4.14.1" + "node-sass": "^4.12.0" } }, "@xtuc/ieee754": { @@ -1791,8 +1791,8 @@ }, "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npm.taobao.org/abbrev/download/abbrev-1.1.1.tgz", - "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=" + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "acorn": { "version": "5.7.4", @@ -1842,7 +1842,7 @@ }, "amdefine": { "version": "1.0.1", - "resolved": "https://registry.npm.taobao.org/amdefine/download/amdefine-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, "ansi-escapes": { @@ -1879,8 +1879,8 @@ }, "are-we-there-yet": { "version": "1.1.5", - "resolved": "https://registry.npm.taobao.org/are-we-there-yet/download/are-we-there-yet-1.1.5.tgz", - "integrity": "sha1-SzXClE8GKov82mZBB2A1D+nd/CE=", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -1912,7 +1912,7 @@ }, "array-find-index": { "version": "1.0.2", - "resolved": "https://registry.npm.taobao.org/array-find-index/download/array-find-index-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" }, "array-union": { @@ -1940,8 +1940,8 @@ }, "asn1": { "version": "0.2.4", - "resolved": "https://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz", - "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "requires": { "safer-buffer": "~2.1.0" } @@ -1995,7 +1995,7 @@ }, "assert-plus": { "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "assign-symbols": { @@ -2012,12 +2012,12 @@ }, "async-foreach": { "version": "0.1.3", - "resolved": "https://registry.npm.taobao.org/async-foreach/download/async-foreach-0.1.3.tgz", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=" }, "asynckit": { "version": "0.4.0", - "resolved": "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "atob": { @@ -2027,13 +2027,13 @@ }, "aws-sign2": { "version": "0.7.0", - "resolved": "https://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npm.taobao.org/aws4/download/aws4-1.11.0.tgz?cache=0&sync_timestamp=1604101166484&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faws4%2Fdownload%2Faws4-1.11.0.tgz", - "integrity": "sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk=" + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==" }, "babel-code-frame": { "version": "6.26.0", @@ -2164,7 +2164,7 @@ }, "bcrypt-pbkdf": { "version": "1.0.2", - "resolved": "https://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "requires": { "tweetnacl": "^0.14.3" @@ -2193,7 +2193,7 @@ }, "block-stream": { "version": "0.0.9", - "resolved": "https://registry.npm.taobao.org/block-stream/download/block-stream-0.0.9.tgz", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "requires": { "inherits": "~2.0.0" @@ -2452,12 +2452,12 @@ }, "camelcase": { "version": "2.1.1", - "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-2.1.1.tgz?cache=0&sync_timestamp=1603923709404&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-2.1.1.tgz", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" }, "camelcase-keys": { "version": "2.1.0", - "resolved": "https://registry.npm.taobao.org/camelcase-keys/download/camelcase-keys-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "requires": { "camelcase": "^2.0.0", @@ -2471,7 +2471,7 @@ }, "caseless": { "version": "0.12.0", - "resolved": "https://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chalk": { @@ -2617,7 +2617,7 @@ }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "collection-visit": { @@ -2644,8 +2644,8 @@ }, "combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.8.tgz", - "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "requires": { "delayed-stream": "~1.0.0" } @@ -2690,7 +2690,7 @@ }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npm.taobao.org/console-control-strings/download/console-control-strings-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "constants-browserify": { @@ -2799,7 +2799,7 @@ }, "cross-spawn": { "version": "3.0.1", - "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", "requires": { "lru-cache": "^4.0.1", @@ -2827,7 +2827,7 @@ }, "currently-unhandled": { "version": "0.4.1", - "resolved": "https://registry.npm.taobao.org/currently-unhandled/download/currently-unhandled-0.4.1.tgz", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "requires": { "array-find-index": "^1.0.1" @@ -2841,7 +2841,7 @@ }, "dashdash": { "version": "1.14.1", - "resolved": "https://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "requires": { "assert-plus": "^1.0.0" @@ -2923,12 +2923,12 @@ }, "delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, "des.js": { @@ -3050,7 +3050,7 @@ }, "ecc-jsbn": { "version": "0.1.2", - "resolved": "https://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "requires": { "jsbn": "~0.1.0", @@ -3144,8 +3144,8 @@ }, "error-ex": { "version": "1.3.2", - "resolved": "https://registry.npm.taobao.org/error-ex/download/error-ex-1.3.2.tgz", - "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "requires": { "is-arrayish": "^0.2.1" } @@ -3496,8 +3496,8 @@ }, "extend": { "version": "3.0.2", - "resolved": "https://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz", - "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=" + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extend-shallow": { "version": "3.0.2", @@ -3589,7 +3589,7 @@ }, "extsprintf": { "version": "1.3.0", - "resolved": "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { @@ -3817,13 +3817,13 @@ }, "forever-agent": { "version": "0.6.1", - "resolved": "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { "version": "2.3.3", - "resolved": "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz", - "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -3879,8 +3879,8 @@ }, "fstream": { "version": "1.0.12", - "resolved": "https://registry.npm.taobao.org/fstream/download/fstream-1.0.12.tgz", - "integrity": "sha1-Touo7i1Ivk99DeUFRVVI6uWTIEU=", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -3901,7 +3901,7 @@ }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npm.taobao.org/gauge/download/gauge-2.7.4.tgz", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "requires": { "aproba": "^1.0.3", @@ -3916,8 +3916,8 @@ }, "gaze": { "version": "1.1.3", - "resolved": "https://registry.npm.taobao.org/gaze/download/gaze-1.1.3.tgz", - "integrity": "sha1-xEFzPhO5J6yMD/C0w7Az8ogSkko=", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", "requires": { "globule": "^1.0.0" } @@ -3934,7 +3934,7 @@ }, "get-stdin": { "version": "4.0.1", - "resolved": "https://registry.nlark.com/get-stdin/download/get-stdin-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" }, "get-value": { @@ -3944,7 +3944,7 @@ }, "getpass": { "version": "0.1.7", - "resolved": "https://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "requires": { "assert-plus": "^1.0.0" @@ -4039,8 +4039,8 @@ }, "globule": { "version": "1.3.2", - "resolved": "https://registry.npm.taobao.org/globule/download/globule-1.3.2.tgz", - "integrity": "sha1-2L3Z6eTu+PluJFmZpd7n612FKcQ=", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", + "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", "requires": { "glob": "~7.1.1", "lodash": "~4.17.10", @@ -4059,13 +4059,13 @@ }, "har-schema": { "version": "2.0.0", - "resolved": "https://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { "version": "5.1.5", - "resolved": "https://registry.npm.taobao.org/har-validator/download/har-validator-5.1.5.tgz", - "integrity": "sha1-HwgDufjLIMD6E4It8ezds2veHv0=", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "requires": { "ajv": "^6.12.3", "har-schema": "^2.0.0" @@ -4099,7 +4099,7 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npm.taobao.org/has-unicode/download/has-unicode-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, "has-value": { @@ -4210,9 +4210,9 @@ } }, "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.8.9.tgz", - "integrity": "sha1-3/wL+aIcAiCQkPKqaUKeFBTa8/k=" + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" }, "htmlparser2": { "version": "3.10.1", @@ -4241,7 +4241,7 @@ }, "http-signature": { "version": "1.2.0", - "resolved": "https://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "requires": { "assert-plus": "^1.0.0", @@ -4298,12 +4298,12 @@ }, "in-publish": { "version": "2.0.1", - "resolved": "https://registry.npm.taobao.org/in-publish/download/in-publish-2.0.1.tgz", - "integrity": "sha1-lIsaU1yAMFYc6lIvc/ePS+NX4Aw=" + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", + "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==" }, "indent-string": { "version": "2.1.0", - "resolved": "https://registry.npm.taobao.org/indent-string/download/indent-string-2.1.0.tgz?cache=0&sync_timestamp=1618679442183&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Findent-string%2Fdownload%2Findent-string-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "requires": { "repeating": "^2.0.0" @@ -4434,7 +4434,7 @@ }, "is-arrayish": { "version": "0.2.1", - "resolved": "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-binary-path": { @@ -4507,12 +4507,12 @@ }, "is-finite": { "version": "1.1.0", - "resolved": "https://registry.nlark.com/is-finite/download/is-finite-1.1.0.tgz", - "integrity": "sha1-kEE1x3+0LAZB1qobzbxNqo2ggvM=" + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz?cache=0&sync_timestamp=1618552489864&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-fullwidth-code-point%2Fdownload%2Fis-fullwidth-code-point-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "requires": { "number-is-nan": "^1.0.0" @@ -4563,12 +4563,12 @@ }, "is-typedarray": { "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-utf8": { "version": "0.2.1", - "resolved": "https://registry.npm.taobao.org/is-utf8/download/is-utf8-0.2.1.tgz", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, "is-windows": { @@ -4598,7 +4598,7 @@ }, "isstream": { "version": "0.1.2", - "resolved": "https://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "js-base64": { @@ -4623,7 +4623,7 @@ }, "jsbn": { "version": "0.1.1", - "resolved": "https://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jsesc": { @@ -4639,7 +4639,7 @@ }, "json-schema": { "version": "0.2.3", - "resolved": "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz?cache=0&sync_timestamp=1609553637722&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-schema%2Fdownload%2Fjson-schema-0.2.3.tgz", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { @@ -4655,7 +4655,7 @@ }, "json-stringify-safe": { "version": "5.0.1", - "resolved": "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json5": { @@ -4668,7 +4668,7 @@ }, "jsprim": { "version": "1.4.1", - "resolved": "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "requires": { "assert-plus": "1.0.0", @@ -4707,7 +4707,7 @@ }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "requires": { "graceful-fs": "^4.1.2", @@ -4719,7 +4719,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -4776,7 +4776,7 @@ }, "loud-rejection": { "version": "1.6.0", - "resolved": "https://registry.npm.taobao.org/loud-rejection/download/loud-rejection-1.6.0.tgz", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "requires": { "currently-unhandled": "^0.4.1", @@ -4808,7 +4808,7 @@ }, "map-obj": { "version": "1.0.1", - "resolved": "https://registry.npm.taobao.org/map-obj/download/map-obj-1.0.1.tgz?cache=0&sync_timestamp=1617771232226&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmap-obj%2Fdownload%2Fmap-obj-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" }, "map-visit": { @@ -4842,7 +4842,7 @@ }, "meow": { "version": "3.7.0", - "resolved": "https://registry.nlark.com/meow/download/meow-3.7.0.tgz", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "requires": { "camelcase-keys": "^2.0.0", @@ -4978,16 +4978,16 @@ } }, "mime-db": { - "version": "1.48.0", - "resolved": "https://registry.nlark.com/mime-db/download/mime-db-1.48.0.tgz?cache=0&sync_timestamp=1622433567590&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmime-db%2Fdownload%2Fmime-db-1.48.0.tgz", - "integrity": "sha1-41sxBF3X6to6qtU37YijOvvvLR0=" + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" }, "mime-types": { - "version": "2.1.31", - "resolved": "https://registry.nlark.com/mime-types/download/mime-types-2.1.31.tgz", - "integrity": "sha1-oA12t0MXxh+cLbIhi46fjpxcnms=", + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", "requires": { - "mime-db": "1.48.0" + "mime-db": "1.44.0" } }, "mimic-fn": { @@ -5140,8 +5140,8 @@ }, "node-gyp": { "version": "3.8.0", - "resolved": "https://registry.nlark.com/node-gyp/download/node-gyp-3.8.0.tgz", - "integrity": "sha1-VAMEJhwzDoDQ1e3OJTpoyzlkIYw=", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", "requires": { "fstream": "^1.0.0", "glob": "^7.0.3", @@ -5159,7 +5159,7 @@ "dependencies": { "semver": { "version": "5.3.0", - "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.3.0.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" } } @@ -5222,8 +5222,8 @@ }, "node-sass": { "version": "4.14.1", - "resolved": "https://registry.nlark.com/node-sass/download/node-sass-4.14.1.tgz", - "integrity": "sha1-mch+wu+3BH7WOPtMnbfzpC4iF7U=", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", + "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", "requires": { "async-foreach": "^0.1.3", "chalk": "^1.1.1", @@ -5246,12 +5246,12 @@ "dependencies": { "ansi-styles": { "version": "2.2.1", - "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-2.2.1.tgz", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.nlark.com/chalk/download/chalk-1.1.3.tgz?cache=0&sync_timestamp=1618995367379&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -5263,14 +5263,14 @@ }, "supports-color": { "version": "2.0.0", - "resolved": "https://registry.nlark.com/supports-color/download/supports-color-2.0.0.tgz?cache=0&sync_timestamp=1622293670728&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" } } }, "nopt": { "version": "3.0.6", - "resolved": "https://registry.npm.taobao.org/nopt/download/nopt-3.0.6.tgz", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "requires": { "abbrev": "1" @@ -5278,8 +5278,8 @@ }, "normalize-package-data": { "version": "2.5.0", - "resolved": "https://registry.npm.taobao.org/normalize-package-data/download/normalize-package-data-2.5.0.tgz", - "integrity": "sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg=", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -5294,8 +5294,8 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npm.taobao.org/npmlog/download/npmlog-4.1.2.tgz", - "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -5305,13 +5305,13 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.nlark.com/number-is-nan/download/number-is-nan-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "oauth-sign": { "version": "0.9.0", - "resolved": "https://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz", - "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=" + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "object-assign": { "version": "4.1.1", @@ -5421,7 +5421,7 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npm.taobao.org/os-homedir/download/os-homedir-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-tmpdir": { @@ -5431,8 +5431,8 @@ }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npm.taobao.org/osenv/download/osenv-0.1.5.tgz", - "integrity": "sha1-hc36+uso6Gd/QW4odZK18/SepBA=", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "requires": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" @@ -5491,7 +5491,7 @@ }, "parse-json": { "version": "2.2.0", - "resolved": "https://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz?cache=0&sync_timestamp=1610966709037&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse-json%2Fdownload%2Fparse-json-2.2.0.tgz", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "requires": { "error-ex": "^1.2.0" @@ -5548,7 +5548,7 @@ }, "path-type": { "version": "1.1.0", - "resolved": "https://registry.npm.taobao.org/path-type/download/path-type-1.1.0.tgz?cache=0&sync_timestamp=1611752058913&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-type%2Fdownload%2Fpath-type-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "requires": { "graceful-fs": "^4.1.2", @@ -5558,7 +5558,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -5578,7 +5578,7 @@ }, "performance-now": { "version": "2.1.0", - "resolved": "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "picomatch": { @@ -5593,12 +5593,12 @@ }, "pinkie": { "version": "2.0.4", - "resolved": "https://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", - "resolved": "https://registry.npm.taobao.org/pinkie-promise/download/pinkie-promise-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "requires": { "pinkie": "^2.0.0" @@ -5708,8 +5708,8 @@ }, "psl": { "version": "1.8.0", - "resolved": "https://registry.npm.taobao.org/psl/download/psl-1.8.0.tgz", - "integrity": "sha1-kyb4vPsBOtzABf3/BWrM4CDlHCQ=" + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "public-encrypt": { "version": "4.0.3", @@ -5773,8 +5773,8 @@ }, "qs": { "version": "6.5.2", - "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz?cache=0&sync_timestamp=1616385315895&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fqs%2Fdownload%2Fqs-6.5.2.tgz", - "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY=" + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "querystring": { "version": "0.2.0", @@ -5809,7 +5809,7 @@ }, "read-pkg": { "version": "1.1.0", - "resolved": "https://registry.npm.taobao.org/read-pkg/download/read-pkg-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "requires": { "load-json-file": "^1.0.0", @@ -5819,7 +5819,7 @@ }, "read-pkg-up": { "version": "1.0.1", - "resolved": "https://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-1.0.1.tgz?cache=0&sync_timestamp=1616916344510&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fread-pkg-up%2Fdownload%2Fread-pkg-up-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "requires": { "find-up": "^1.0.0", @@ -5828,7 +5828,7 @@ "dependencies": { "find-up": { "version": "1.1.2", - "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-1.1.2.tgz?cache=0&sync_timestamp=1599054261724&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-up%2Fdownload%2Ffind-up-1.1.2.tgz", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "requires": { "path-exists": "^2.0.0", @@ -5837,7 +5837,7 @@ }, "path-exists": { "version": "2.1.0", - "resolved": "https://registry.npm.taobao.org/path-exists/download/path-exists-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "requires": { "pinkie-promise": "^2.0.0" @@ -5877,7 +5877,7 @@ }, "redent": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/redent/download/redent-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "requires": { "indent-string": "^2.1.0", @@ -5977,7 +5977,7 @@ }, "repeating": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/repeating/download/repeating-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "requires": { "is-finite": "^1.0.0" @@ -5985,8 +5985,8 @@ }, "request": { "version": "2.88.2", - "resolved": "https://registry.npm.taobao.org/request/download/request-2.88.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frequest%2Fdownload%2Frequest-2.88.2.tgz", - "integrity": "sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM=", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -6030,12 +6030,6 @@ "resolve-from": "^1.0.0" } }, - "reserved-words": { - "version": "0.1.2", - "resolved": "https://registry.npm.taobao.org/reserved-words/download/reserved-words-0.1.2.tgz", - "integrity": "sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=", - "dev": true - }, "resolve": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", @@ -6184,8 +6178,8 @@ }, "sass-graph": { "version": "2.2.5", - "resolved": "https://registry.npm.taobao.org/sass-graph/download/sass-graph-2.2.5.tgz", - "integrity": "sha1-qYHIdEa4MZ2W3OBnHkh4eb0kwug=", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", + "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", "requires": { "glob": "^7.0.0", "lodash": "^4.0.0", @@ -6214,7 +6208,7 @@ }, "scss-tokenizer": { "version": "0.2.3", - "resolved": "https://registry.npm.taobao.org/scss-tokenizer/download/scss-tokenizer-0.2.3.tgz", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", "requires": { "js-base64": "^2.1.8", @@ -6223,7 +6217,7 @@ "dependencies": { "source-map": { "version": "0.4.4", - "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.4.4.tgz", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "requires": { "amdefine": ">=0.0.4" @@ -6502,8 +6496,8 @@ }, "spdx-correct": { "version": "3.1.1", - "resolved": "https://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.1.1.tgz", - "integrity": "sha1-3s6BrJweZxPl99G28X1Gj6U9iak=", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -6511,22 +6505,22 @@ }, "spdx-exceptions": { "version": "2.3.0", - "resolved": "https://registry.npm.taobao.org/spdx-exceptions/download/spdx-exceptions-2.3.0.tgz", - "integrity": "sha1-PyjOGnegA3JoPq3kpDMYNSeiFj0=" + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" }, "spdx-expression-parse": { "version": "3.0.1", - "resolved": "https://registry.npm.taobao.org/spdx-expression-parse/download/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha1-z3D1BILu/cmOPOCmgz5KU87rpnk=", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { - "version": "3.0.9", - "resolved": "https://registry.nlark.com/spdx-license-ids/download/spdx-license-ids-3.0.9.tgz?cache=0&sync_timestamp=1621652583280&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fspdx-license-ids%2Fdownload%2Fspdx-license-ids-3.0.9.tgz", - "integrity": "sha1-illRNd75WSvaaXCUdPHL7qfCRn8=" + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" }, "split-string": { "version": "3.1.0", @@ -6544,8 +6538,8 @@ }, "sshpk": { "version": "1.16.1", - "resolved": "https://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz", - "integrity": "sha1-+2YcC+8ps520B2nuOfpwCT1vaHc=", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -6588,8 +6582,8 @@ }, "stdout-stream": { "version": "1.4.1", - "resolved": "https://registry.npm.taobao.org/stdout-stream/download/stdout-stream-1.4.1.tgz", - "integrity": "sha1-WsF0zdXNcmEEqgwLK9g4FdjVNd4=", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", "requires": { "readable-stream": "^2.0.1" } @@ -6635,7 +6629,7 @@ }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.nlark.com/string-width/download/string-width-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { "code-point-at": "^1.0.0", @@ -6679,7 +6673,7 @@ }, "strip-bom": { "version": "2.0.0", - "resolved": "https://registry.nlark.com/strip-bom/download/strip-bom-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "requires": { "is-utf8": "^0.2.0" @@ -6687,7 +6681,7 @@ }, "strip-indent": { "version": "1.0.1", - "resolved": "https://registry.nlark.com/strip-indent/download/strip-indent-1.0.1.tgz?cache=0&sync_timestamp=1620053310624&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fstrip-indent%2Fdownload%2Fstrip-indent-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "requires": { "get-stdin": "^4.0.1" @@ -6785,8 +6779,8 @@ }, "tar": { "version": "2.2.2", - "resolved": "https://registry.npm.taobao.org/tar/download/tar-2.2.2.tgz", - "integrity": "sha1-DKiEhWLHKZuLRG/2pNYM27I+3EA=", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", "requires": { "block-stream": "*", "fstream": "^1.0.12", @@ -6936,8 +6930,8 @@ }, "tough-cookie": { "version": "2.5.0", - "resolved": "https://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.5.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftough-cookie%2Fdownload%2Ftough-cookie-2.5.0.tgz", - "integrity": "sha1-zZ+yoKodWhK0c72fuW+j3P9lreI=", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "requires": { "psl": "^1.1.28", "punycode": "^2.1.1" @@ -6945,13 +6939,13 @@ }, "trim-newlines": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/trim-newlines/download/trim-newlines-1.0.0.tgz?cache=0&sync_timestamp=1623341510447&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftrim-newlines%2Fdownload%2Ftrim-newlines-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" }, "true-case-path": { "version": "1.0.3", - "resolved": "https://registry.npm.taobao.org/true-case-path/download/true-case-path-1.0.3.tgz", - "integrity": "sha1-+BO1qMhrQNpZYGcisUTjIleZ9H0=", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", "requires": { "glob": "^7.1.2" } @@ -6969,7 +6963,7 @@ }, "tunnel-agent": { "version": "0.6.0", - "resolved": "https://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { "safe-buffer": "^5.0.1" @@ -6977,7 +6971,7 @@ }, "tweetnacl": { "version": "0.14.5", - "resolved": "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "type-check": { @@ -7151,8 +7145,8 @@ }, "uuid": { "version": "3.4.0", - "resolved": "https://registry.nlark.com/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1622213136953&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz", - "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=" + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "v8-compile-cache": { "version": "2.1.1", @@ -7167,8 +7161,8 @@ }, "validate-npm-package-license": { "version": "3.0.4", - "resolved": "https://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -7176,7 +7170,7 @@ }, "verror": { "version": "1.10.0", - "resolved": "https://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "requires": { "assert-plus": "^1.0.0", @@ -7525,8 +7519,8 @@ }, "wide-align": { "version": "1.1.3", - "resolved": "https://registry.npm.taobao.org/wide-align/download/wide-align-1.1.3.tgz", - "integrity": "sha1-rgdOa9wMFKQx6ATmJFScYzsABFc=", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "requires": { "string-width": "^1.0.2 || 2" } @@ -7681,8 +7675,8 @@ }, "zlib": { "version": "1.0.5", - "resolved": "https://registry.npm.taobao.org/zlib/download/zlib-1.0.5.tgz", + "resolved": "https://registry.npmjs.org/zlib/-/zlib-1.0.5.tgz", "integrity": "sha1-bnyXL8NxxkWmr7A6sUdp3vEU/MA=" } } -} +} \ No newline at end of file From 2dbbd3501405a7540aecb85fc175543fd6cb0527 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Thu, 15 Jul 2021 10:08:51 +0800 Subject: [PATCH 17/20] =?UTF-8?q?fix:=20=E8=BF=98=E5=8E=9Fpackage.json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/wxa-cli/package.json b/packages/wxa-cli/package.json index dab15fbc..22e57d86 100644 --- a/packages/wxa-cli/package.json +++ b/packages/wxa-cli/package.json @@ -69,6 +69,7 @@ "promise.prototype.finally": "^3.1.0", "shelljs": "^0.8.3", "tapable": "^1.0.0", + "valid-url": "^1.0.9", "lodash": "^4.17.21" }, "publishConfig": { From 25e497384a2c07bd1e8ee81194ad8eccfe2aa005 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Thu, 15 Jul 2021 17:29:58 +0800 Subject: [PATCH 18/20] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0lodash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 6 +++--- package.json | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 39ffa5c1..0a6689c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12136,9 +12136,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.21", + "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.21.tgz?cache=0&sync_timestamp=1613835838133&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.21.tgz", + "integrity": "sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw=" }, "lodash._reinterpolate": { "version": "3.0.0", diff --git a/package.json b/package.json index 1931445b..b080ba25 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ }, "dependencies": { "@vuepress/theme-default": "^1.5.4", + "lodash": "^4.17.21", "vue-server-renderer": "^2.6.12" } } From 29e2ef11f24f073b45d6d715d13079f2d245d1af Mon Sep 17 00:00:00 2001 From: sparklinm Date: Sun, 1 Aug 2021 17:21:20 +0800 Subject: [PATCH 19/20] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=86=B2?= =?UTF-8?q?=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wxa-cli/package-lock.json | 62 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/packages/wxa-cli/package-lock.json b/packages/wxa-cli/package-lock.json index e4b1b000..f90277a4 100644 --- a/packages/wxa-cli/package-lock.json +++ b/packages/wxa-cli/package-lock.json @@ -1738,9 +1738,9 @@ } }, "@wxa/compiler-babel": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@wxa/compiler-babel/-/compiler-babel-2.2.0.tgz", - "integrity": "sha512-kjQL/T0vLdulAoaCVzlmAE3UbtC1e/c6JVmf/OL9hi7oDspAhlyHSySOH9JhTGYzOKPYbJpBrO1EoMMsnLWRMA==", + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@wxa/compiler-babel/-/compiler-babel-2.2.7.tgz", + "integrity": "sha512-BX+Mft8cXGnarS1CgxhrujW4yHnnyQvKAm+l7D9CI3da4UwYkqzA/2XicQG0Zu5gIrekvvosUp8zRE9truZepA==", "requires": { "@babel/core": "^7.1.0", "debug": "^4.0.1", @@ -1750,11 +1750,11 @@ }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "find-cache-dir": { @@ -1770,11 +1770,11 @@ } }, "@wxa/compiler-sass": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@wxa/compiler-sass/-/compiler-sass-2.2.0.tgz", - "integrity": "sha512-te92dBDbVQDMaqaTopmK9pIx8W2WWg3bESVv4T71WS4UHLzy3boqnjICS5w4ZfCHpeL4imvMiAVZe37tHcT3Jw==", + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@wxa/compiler-sass/-/compiler-sass-2.2.7.tgz", + "integrity": "sha512-bQfqxJbTFrfWN5uVSR/ajLMQ/olyKAMvGBYUHcmZMUDl1zYzi1ldM3d7CrDFMaaPgdsJMqUV0fSVQGDSzyWjoQ==", "requires": { - "node-sass": "^4.12.0" + "node-sass": "^4.14.1" } }, "@xtuc/ieee754": { @@ -2031,9 +2031,9 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==" + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, "babel-code-frame": { "version": "6.26.0", @@ -4210,9 +4210,9 @@ } }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" }, "htmlparser2": { "version": "3.10.1", @@ -4762,9 +4762,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "loose-envify": { "version": "1.4.0", @@ -4978,16 +4978,16 @@ } }, "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", + "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==" }, "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.32", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", + "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", "requires": { - "mime-db": "1.44.0" + "mime-db": "1.49.0" } }, "mimic-fn": { @@ -6518,9 +6518,9 @@ } }, "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==" }, "split-string": { "version": "3.1.0", @@ -7679,4 +7679,4 @@ "integrity": "sha1-bnyXL8NxxkWmr7A6sUdp3vEU/MA=" } } -} \ No newline at end of file +} From ebc8f3891b1a46b366176d8df5e81475ccf3c903 Mon Sep 17 00:00:00 2001 From: sparklinm Date: Fri, 25 Mar 2022 17:49:38 +0800 Subject: [PATCH 20/20] =?UTF-8?q?fix:=20=E6=98=AF=E5=90=A6=E5=BC=80?= =?UTF-8?q?=E5=90=AF=20tree-shake=20=E5=8F=AF=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cli/configuration.md | 7 +++++++ packages/wxa-cli/src/const/wxaConfigs.js | 1 + packages/wxa-cli/src/schedule.js | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/cli/configuration.md b/docs/cli/configuration.md index 72009746..48567c96 100644 --- a/docs/cli/configuration.md +++ b/docs/cli/configuration.md @@ -146,6 +146,13 @@ module.exports = { ### optimization.allowEmptyAttributes 是否允许空属性,默认 `true`,不要改动该配置,除非你清楚自己要做什么:warning:。 +## treeShake + +- **类型**: `Boolean` default: `false` +- **用法**: + +是否开启 `tree-shake` 。只有为 `true` 且非 `watch` 模式下 `tree-shake` 才会生效。 + ## plugins 目前支持的插件有: diff --git a/packages/wxa-cli/src/const/wxaConfigs.js b/packages/wxa-cli/src/const/wxaConfigs.js index 4e6b28d7..504e03ce 100644 --- a/packages/wxa-cli/src/const/wxaConfigs.js +++ b/packages/wxa-cli/src/const/wxaConfigs.js @@ -43,6 +43,7 @@ export default class DefaultWxaConfigs { allowEmptyAttributes: true, transformPxToRpx: false, }, + treeShake: false, }; } } diff --git a/packages/wxa-cli/src/schedule.js b/packages/wxa-cli/src/schedule.js index b15eeed9..a0ed5fcb 100644 --- a/packages/wxa-cli/src/schedule.js +++ b/packages/wxa-cli/src/schedule.js @@ -126,7 +126,7 @@ class Schedule { while (this.$depPending.length) { let dep = this.$depPending.shift(); - if (!this.cmdOptions.watch && dep.src.endsWith('.js')) { + if (this.wxaConfigs.treeShake && !this.cmdOptions.watch && dep.src.endsWith('.js')) { this.$depJsPending.push(dep); } else { tasks.push(this.$parse(dep)); @@ -139,7 +139,7 @@ class Schedule { if (this.$depPending.length === 0) { // dependencies resolve complete - if (!this.cmdOptions.watch) { + if (this.wxaConfigs.treeShake && !this.cmdOptions.watch) { let sub = await this.$dojsDPA(); return succ.concat(sub); }