• 修剪AST树减少webapck打包尺寸


    背景

    公司每年都有不同的H5活动(vue2)上线、下线,这些代码都在存在于同一个仓库中。

    虽然过期的活动代码,增加了无效的编译时间和打包内容,但是我们并不想删除它们,毕竟代码即资产。

    所以,我们希望实现一种方案,既能保留所有活动路由,又能将过期活动内容从包中剔除。

    webpack loader

    loader 用于对模块的源代码进行转换。我们可以编写一个 loader 来参与 webpack 打包过程,进而修改源代码。一个最简单的 loader 如下——它把接收到的源码原封不动的返回了:

    module.exports = function doNothingLoader(content) {
      return content
    }
    

    修剪路由AST

    使用自定义 loader,我们就可以在 webpack 打包时修改源码而不会产生副作用。具体的思路是:通过this.resourcePath识别源代码是否为路由文件,若是,则解析代码,并将其中的component字段删除,以达到保留路由而删除内容的目的。

    router.js源码

    import router from "@/router";
    const routes = [{
      name: 'test',
      path: '/promotion/test',
      component: () => import(/* webpackChunkName: 'promotion/pages/test' */'./pages/test/index'),
      meta: {
        title: '测试'
      }
    }]
    router.addRoutes(routes);
    

    修剪后(删除了 component 字段)

    import router from "@/router";
    const routes = [{
      name: 'test',
      path: '/promotion/test',
    
      meta: {
        title: '测试'
      }
    }]
    router.addRoutes(routes);
    

    代码实现

    通过 babel 插件,可以修改 babel 转换后的 AST 树。复制任何有效的JS代码到astexplorer,能够非常清晰的看到其AST结构。

    我们要做的事就变得很简单了:如果是路由文件,则遍历其 AST,找到component字段并删除。

    const babel = require('babel-core'); // v6.26.0
    const isWin = /^win/.test(process.platform)
    const normalizePath = path => (isWin ? path.replace(/\\/g, '/') : path)
    const routerRegx = /projects\/test\/(.*)router\.js/
    const isInvalidRoute = () => null // 根据项目实际情况实现 isInvalidRoute
    
    const pruneInvalidRoute = {
      visitor: {
        ObjectExpression(path) {
          const pathNode = (path.node.properties || []).find(p => p.key.name === 'path') 
          if (pathNode) {
            const routeVal = pathNode.value.value || ''
            if (isInvalidRoute(routeVal) {
              const compIndex = properties.findIndex(p => p.key.name === 'component')
              if (compIndex >= 0) {
                properties.splice(compIndex, 1)
                return
              }
            }
          }
        }
      }
    }
    
    module.exports = function pruneInvalidRouteLoader(content) {
      const filePath = normalizePath(this.resourcePath)
      const matched = routerRegx.test(filePath)
      if (!matched) return content
      const result = babel.transformFileSync(filePath, {plugins: [pruneInvalidRoute]})
      return result.code
    }
    
    

    唯一要注意的是,由于 babel 的版本差异,其接口略有不同,具体可查看版本对应文档。本文所用的babel-core版本为:6.26.0。

  • 相关阅读:
    sqlite 一些常用的句子
    SnackBar使用
    semaphore demo 并行 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    Expanded, SingleChildScrollView, CustomScrollView, container, height, width
    2个监听器+ dialog + replysubject + extends
    Transparent PageRoute in Flutter for displaying a (semi-) transparent page
    股票价格指数+加权
    Dojo
    iOS各版本图标尺寸汇总
    Xcode6 storyboard new push segue 后的视图控制器没有navigation item bug.
  • 原文地址:https://www.cnblogs.com/fayin/p/15630207.html
Copyright © 2020-2023  润新知