资讯专栏INFORMATION COLUMN

自动 Import 工具,前端打字员的自我救赎

DevYK / 1542人阅读

摘要:自动工具先推荐两个干货,关于正则的,,前者验证正则是否和预期一样,后者以图的形式表达正则,有助于理解天书般的别人写的正则作为一个前端打字员,一个经常遇到的场景就是在路由文件中引入模块,比如这样在中写入如果修改了模块的名字,增加了模块或者删

自动 import 工具

先推荐两个干货,关于正则的
regexr,regexper,前者验证正则是否和预期一样,后者以图的形式表达正则,有助于理解天书般的别人写的正则

作为一个前端打字员,一个经常遇到的场景就是在路由文件中引入模块,比如这样

router/index.js 中写入

import Vue from "vue"
import Router from "vue-router"

const About = () => import("../pages/About.vue")
const Home = () => import("../pages/Home.vue")

Vue.use(Router)
...

如果修改了模块的名字,增加了模块或者删除了模块,就需要重新修改这个路由文件

总是做这么机械的事情无异于消耗我这个前端打字员的寿命

不能忍,遂写个工具

整理思路如下

其中,监视目录下文件的变动依靠的是 node API 中fs.watch(filename[, options][, listener])

替换目标文件中引入模块的部分,则是通过正则来实现

在这里五星推荐一个验证正则是否正确的网站,regexr

代码实现

监视包含模块的目录

fs.watch(dir, {
  recursive: true // 目录下子目录也被监视
}, (event, filename) => { 
// event 是文件变动的类型,添加文件、删除文件和修改文件名都是"rename" 事件
// filename 是变化的文件或目录
  if(event === "rename"){ // 判断文件变动类型
    
  }
})

当发生rename事件后,需要重新获得目录下(from)所有的模块,包括模块名moduleName,模块文件相对于引用模块文件(to)的相对路径modulePath,将它们存入变量modules

实际项目中,模块通常都是.vue文件,或者.jsx文件,因此只将这些作为模块,在路由文件中引用

另外有些模块文件因为各种原因,希望人工引入,而不被watch,这样的文件存入excludeArr

const _ = require("lodash")
let excludeArr = [...]
let modules = []
let extname = ".vue"
let from = "./src/pages"
let to = "./src/router/index.js""

const mapDir = d => {
    // 获得当前文件夹下的所有的文件夹和文件
    const [dirs, files] = _(fs.readdirSync(d)).partition(p =>
        fs.statSync(path.join(d, p)).isDirectory()
    )

    // 映射文件夹
    dirs.forEach(dir => {
        modules.concat(mapDir(path.join(d, dir)))
    })

    // 映射文件
    files.forEach(file => {
        // 文件后缀名
        let filename = path.join(d, file)
        if (path.extname(file) === extname) {
            if (!excludeArr.includes(path.resolve(__dirname, filename))) {
                let moduleName = path.basename(file, extname)
                // 若存在 -
                if (moduleName.match("-")) {
                    moduleName = moduleName.replace(
                        /(-)(.{1})/,
                        (match, p1, p2, offset, string) => p2.toUpperCase()
                    )
                }
                modules.push({
                    moduleName,
                    modulePath: path.relative(path.dirname(to), filename)
                })
            }
        }
    })
}

生成好新的待引入的模块后,接下来就是在路由文件中,将对应的内容替换掉

所以需要读写文件以及正则替换

                const regex = //*sautoImport(.*
)*/*sautoImports*//g
                let importStr = ""
                modules.forEach((m, index) => {
                    importStr =
                        importStr +
                        fillTemplate(template, m.moduleName, m.modulePath) +
                        (cache.length - 1 === index ? "" : "
")
                })
                fs.readFile(to, "utf8", (err, data) => {
                    if (err) return console.log(err)
                    let result = ""
                    if (data.match(regex)) {
                        result = data.replace(
                            regex,
                            `/* autoImport */
${importStr}
/* autoImport */`
                        )
                    } else {
                        /* 首次插入在文件最后的import插入 */
                        result = data.replace(
                            /(.*import.*)(
)([^(import)])/,
                            (match, p1, p2, p3, offset, string) => {
                                return `${p1}
/* autoImport */
${importStr}
/* autoImport */
${p3}`
                            }
                        )
                    }

                    fs.writeFile(to, result, "utf8", err => {
                        if (err) return console.log(err)
                    })
                })

其中//*sautoImport(.* )*/*sautoImports*//g是用于匹配两段注释/* autoImport */及其中间的内容

import Vue from "vue"
import Router from "vue-router"
/* autoImport */
const About = () => import("../pages/About.vue")
const Home = () => import("../pages/Home.vue")
/* autoImport */

Vue.use(Router)

当第一次使用,没有/* autoImport */时,就需要在最后一个import后面,插入引入的模块

data.replace(
                            /(.*import.*)(
)([^(import)])/,
                            (match, p1, p2, p3, offset, string) => {
                                return `${p1}
/* autoImport */
${importStr}
/* autoImport */
${p3}`

在这里还可以自定义了引入模块的方式,例如懒加载,"const moduleName = () => import(modulePath)"

const template = "const moduleName = () => import(modulePath)"
const fillTemplate = (template, moduleName, modulePath) =>
    template
        .replace("moduleName", moduleName)
        .replace("modulePath", `"${modulePath}"`)

为了工具的灵活性,把可配置项写成json文件的形式

{
    "extname": ".vue",
    "from": "src/pages",
    "to": "src/router/index.js",
    "template": "const moduleName = () => import(modulePath)",
    "exclude": [
        "./src/pages/login.vue",
        "./src/pages/404.vue",
        "./src/pages/overall/**",
        "./src/pages/account-result/**"
    ]
}

然后通过以下的方式来获得

const config = fs.readFileSync("./autoImport.json")
const { extname, from, to, template, exclude } = JSON.parse(config)
后记

下一步准备把这个工具写成webpack的插件,名字我都起好了,AutoImportPlugin,先在github上占了个坑,顺手给颗星,不用改Bug

同时准备用更加成熟的模块chokidar来代替原生的watch

工具有问题提issue啊

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92311.html

相关文章

  • 记第一次发布npm包经历,smart-import

    摘要:故事背景前情提要自动工具,前端打字员的自我救赎的功能根据配置文件,在目标文件中自动导入规定目录下自定义模块,并监听规定目录下文件的变动,自动更新尚在测试中的使用安装工具编写配置文件需要自动导入的模块的后缀名自动导入的模块的来源目 故事背景 前情提要:自动 Import 工具,前端打字员的自我救赎 github: smart-import smart-import 的功能 根据配置文件...

    Raaabbit 评论0 收藏0
  • 重构smart-import

    摘要:前情提要自动工具,前端打字员的自我救赎记第一次发布包经历,是重构中的代码是版本可以工作的代码配置文件待导入的模块引用模块的文件引用模块的方式忽略的模块实现监听文件的删除和添加以上代码主要使用了来监听文件的变化。 前情提要 自动 Import 工具,前端打字员的自我救赎 记第一次发布npm包经历,smart-import GitHub:smart-import develop是重构中的代...

    Pocher 评论0 收藏0
  • 一道多线程面试题引起自我救赎

    摘要:重温一个面试题内容数组内容为数组内容为个英文字母,使用两个线程分别输入两个数组,打印内容为这样的规律提取一下核心内容,去除次要内容两个线程需要交替执行,打印数字的线程需要先执行,数组打印完毕后线程需要结束。 一道多线程面试题引起的自我救赎 近日去一个知名互联网企业参加面试,之前准备多多信心满满,但是面试一开始就是一道不起眼的编程题 数组A内容为 1,2,3,4...52 ,数组B内容...

    BaronZhang 评论0 收藏0
  • 普通大一学生自我反思

    摘要:听了鹏哥的教导,也开始写起了博客现在多粉,感觉都是机器人哈哈,最近粉丝也不涨了,不知道是不是我最近不发文章的原因。这一个多月,基本就是学刷算法题。在这里不得不吐槽一下学校,每条早上做早操,晚自习到点,感觉浪费了我很多学习技术的时间。 ...

    callmewhy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<