做网站联系方式,互联网行业分析,wordpress上传图片,营销型单页面网站制作写一个vite插件去除代码中的console
使用babel做处理。简单处理#xff0c;复杂情况未考虑。 学习babel写的demo。
项目根目录新建文件 babel-plugin-remove-console.js rollup-plugin-remove-console.js babel-plugin-remove-console.js
import { declare } from babel/he…写一个vite插件去除代码中的console
使用babel做处理。简单处理复杂情况未考虑。 学习babel写的demo。
项目根目录新建文件 babel-plugin-remove-console.js rollup-plugin-remove-console.js babel-plugin-remove-console.js
import { declare } from babel/helper-plugin-utils;const removeConsolePlugin declare((api, options, dirname) {api.assertVersion(7);return {visitor: {CallExpression(path) {// 检查是否是console.method()调用const { callee } path.node;if (callee.type MemberExpression callee.object.type Identifier callee.object.name console callee.property.type Identifier) {// 如果是独立语句 (ExpressionStatement)直接移除整个语句if (path.parent.type ExpressionStatement) {path.parentPath.remove();}// 否则替换为undefined (避免语法错误)else {path.replaceWith(api.types.identifier(undefined));}return;}},},};
});export default removeConsolePlugin;为什么要处理这些呢 callee.type MemberExpression callee.object.type Identifier callee.object.name console callee.property.type Identifier在https://astexplorer.net/ 可以尝试下
当然也可以写成这样 visitor: {MemberExpression(path){if(path.node.object.nameconsole){console.log(path.parentPath.node)path.parentPath.remove();}}},rollup-plugin-remove-console.js
import { createFilter } from rollup/pluginutils;
import { transformFromAstSync } from babel/core;
import parser from babel/parser;
import removeConsolePlugin from ./babel-plugin-remove-console;
export default function myPlugin(pluginOptions {}) {const defaultExclude /node_modules/;// 如果用户提供了exclude选项合并默认排除const excludePattern pluginOptions.exclude? [defaultExclude, pluginOptions.exclude]: defaultExclude;const filter createFilter(pluginOptions.include || /\.(js|ts|jsx|tsx|vue)$/,excludePattern);return {name: rollup-plugin-remove-console,transform(src, id) {if (!filter(id)) {return null;}const ast parser.parse(src, {sourceType: unambiguous,});const { code, map } transformFromAstSync(ast, src, {plugins: [[removeConsolePlugin]],});return {code,map, // 或者提供一个 sourcemap 对象};},};
}vite.config.js引入使用 如果你使用了多个插件需要把自己定义的这个去除插件放到最后面等其他代码都转换完毕后只需要处理js语法即可。 比如我们这里引入了vuejsx,支持vuejsx语法。
他是怎么处理的呢。 一般vue编译的时候会把vue文件中的样式模版脚本拆分。
我这里的jsx写法所以是lang.jsx 经过vue,vuejsx插件的加工后成了这样 所以我们只需要考虑console本身即可。
扩展
忽略某些
增加配置来处理如我们可以配置console的哪些方法不移除或者哪些方法移除。 在vite插件中将pluginOptions传递给babel插件这里文件名起的是rollup-plugin-remove-console.js因为没用到vite的特性hooks所以也支持rollup(按理来说不过没有测试)。 可以看到传递过来的参数。
怎么获取是log还是warn还是error呢。 所以要获取下 const name path.node.property.name;
import { declare } from babel/helper-plugin-utils;
const removeConsolePlugin declare((api, options, dirname) {api.assertVersion(7);const ignores options.ignore || [];return {visitor: {MemberExpression(path) {if (path.node.object.name console) {const name path.node.property.name;const isIgnore ignores.includes(name);if (!isIgnore) {path.parentPath.remove();}}},},};
});export default removeConsolePlugin;
或者
import { declare } from babel/helper-plugin-utils;
const removeConsolePlugin declare((api, options, dirname) {api.assertVersion(7);const ignores options.ignore || [];return {visitor: {CallExpression(path) {// 检查是否是console.method()调用const { callee } path.node;if (callee.type MemberExpression callee.object.type Identifier callee.object.name console callee.property.type Identifier) {const name callee.property.name;const isIgnore ignores.includes(name);if (!isIgnore) {// 如果是独立语句 (ExpressionStatement)直接移除整个语句if (path.parent.type ExpressionStatement) {path.parentPath.remove();}// 否则替换为undefined (避免语法错误)else {path.replaceWith(api.types.identifier(undefined));}}}},},};
});export default removeConsolePlugin; 替换
比如我们有这样两个个函数。上报数据上报异常。 假设在开发环境我们不需要上报也就是开发环境不替换一般也是开发环境不替换。 我们需要在插件运行前获取环境 传递给babel插件 当然其实这一步不用你可以在babe插件里面直接获取。 在babel插件里面接收下。
如果不是开发环境就执行插件。 或者我们简单点。
在vite插件中直接不往下走了不执行babel插件了。 然后继续完善替换的逻辑。 假设我们的插件是这样传递参数的。 babel获取下
替换的逻辑为 当匹配上的时候把原先的参数带进去再额外携带一个文件的信息。 source为来源。 source大概这样 然后我们看下效果。 开发环境
build后 完整代码
rollup-plugin-remove-console.js
rollup-plugin-remove-console.js
import { createFilter } from rollup/pluginutils;
import { transformFromAstSync } from babel/core;
import parser from babel/parser;
import removeConsolePlugin from ./babel-plugin-remove-console;
export default function myPlugin(pluginOptions {}) {const defaultExclude /node_modules/;let isDev false;// 如果用户提供了exclude选项合并默认排除const excludePattern pluginOptions.exclude? [defaultExclude, pluginOptions.exclude]: defaultExclude;const filter createFilter(pluginOptions.include || /\.(js|ts|jsx|tsx|vue)$/,excludePattern);// console.log(pluginOptions);return {name: rollup-plugin-remove-console,options(inputOptions) {isDev process.env.NODE_ENV development;console.log(isDev, isDev);return inputOptions;},transform(src, id) {if (!filter(id) || isDev) {return null;}const ast parser.parse(src, {sourceType: unambiguous,});const paths id.split(/);const source paths[paths.length - 1];console.log(source);const { code, map } transformFromAstSync(ast, src, {plugins: [[removeConsolePlugin, { ...pluginOptions, source, isDev }]],});return {code,map, // 或者提供一个 sourcemap 对象};},};
}
babel-plugin-remove-console.js
babel-plugin-remove-console.js
import { declare } from babel/helper-plugin-utils;
import { types as t } from babel/core;const removeConsolePlugin declare((api, options, dirname) {api.assertVersion(7);const ignores options.ignore || [];const replaceList options.replaceList || [];const source options.source;let isDev process.env.NODE_ENV development;if (typeof options.isDev ! undefined) {isDev options.isDev;}return {visitor: {MemberExpression(path) {if (path.node.object.name console !isDev) {const name path.node.property.name;const replaceItem replaceList.find((item) item[0] name);if (replaceItem) {const replaceName replaceItem[1];if (!replaceName) {console.warn(请配置替换的函数);}if (replaceList.length 0) {const args path.parentPath.node.arguments;const loggerCall t.callExpression(t.identifier(replaceName), [...args,t.stringLiteral(source),]);loggerCall.isDone true;path.parentPath.replaceWith(loggerCall);}}const isIgnore ignores.includes(name);if (!isIgnore) {path.parentPath.remove();}}},},};
});export default removeConsolePlugin;
vite.config.js
import { defineConfig } from vite;
import vue from vitejs/plugin-vue;
import rollupPluginRemoveConsole from ./rollup-plugin-remove-console.js;
import vueJsx from vitejs/plugin-vue-jsx;// https://vite.dev/config/
export default defineConfig({//plugins: [vue(),vueJsx(),rollupPluginRemoveConsole({ignore: [log, error],replaceList: [[log, uploadLog],[error, uploadError],],}),],base: ./,server: {proxy: {/api: {target: http://localhost:3000/,changeOrigin: true,rewrite: (path) path.replace(/^\/api/, ),},},},
});
main.js
import { createApp } from vue;
import ./style.css;
import App from ./App.vue;const upData (type, args) {fetch(/api/${type}, {method: POST,headers: {Content-Type: application/json,},body: JSON.stringify(args),});
};window.uploadLog (...args) {upData(log, args);
};
window.uploadError (...args) {upData(error, args);// fetch
};createApp(App).mount(#app);