最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 精通Vite2之插件开发指南

    正文概述 掘金(杨村长)   2021-04-13   716
    精通Vite2之插件开发指南

    前几篇文章我写了一下Vite2在工程化和项目实践中的一些探索,受到了小伙伴们的喜爱,其中就有人提出想看看vite插件怎么写,我看了一下文档、vite-plugin-mock和vite-plugin-vue-i18n的源码,有一些收获,在这里分享给大家,本文内容如下:

    • Vite2插件开发指南
      • Vite插件是什么
      • Vite插件的形式
      • 插件钩子
      • 插件顺序
      • 插件编写实操
      • 配套视频教程
      • 配套源码
      • 后续创作计划
      • 支持我们

    Vite插件是什么

    使用Vite插件可以扩展Vite能力,比如解析用户自定义的文件输入,在打包代码前转译代码,或者查找第三方模块。

    精通Vite2之插件开发指南

    Vite插件的形式

    Vite插件扩展自Rollup插件接口,只是额外多了一些Vite特有选项。

    Vite插件是一个拥有名称创建钩子(build hook)或生成钩子(output generate hook)的对象

    精通Vite2之插件开发指南

    如果需要配置插件,它的形式应该是一个接收插件选项,返回插件对象的函数

    精通Vite2之插件开发指南

    范例:加载一个不存在的虚拟模块

    创建vite-plugin-my-example.js

    export default function myExample () {
      return {
        name: 'my-example', // 名称用于警告和错误展示
        resolveId ( source ) {
          if (source === 'virtual-module') {
            return source; // 返回source表明命中,vite不再询问其他插件处理该id请求
          }
          return null; // 返回null表明是其他id要继续处理
        },
        load ( id ) {
          if (id === 'virtual-module') {
            return 'export default "This is virtual!"'; // 返回"virtual-module"模块源码
          }
          return null; // 其他id继续处理
        }
      };
    }
    

    插件钩子

    通用钩子

    开发时,Vite dev server创建一个插件容器按照Rollup调用创建钩子的规则请求各个钩子函数。

    下面钩子会在服务器启动时调用一次:

    • options 替换或操纵rollup选项
    • buildStart 开始创建

    下面钩子每次有模块请求时都会被调用:

    • resolveId 创建自定义确认函数,常用语定位第三方依赖
    • load 创建自定义加载函数,可用于返回自定义的内容
    • transform 可用于转换已加载的模块内容

    下面钩子会在服务器关闭时调用一次:

    • buildEnd
    • closeBundle

    Vite特有钩子

    • config: 修改Vite配置
    • configResolved:Vite配置确认
    • configureServer:用于配置dev server
    • transformIndexHtml:用于转换宿主页
    • handleHotUpdate:自定义HMR更新时调用

    范例:钩子调用顺序测试

    export default function myExample () {
      // 返回的是插件对象
      return {
        name: 'hooks-order', 
        // 初始化hooks,只走一次
        options(opts) {
          console.log('options', opts);
        },
        buildStart() {
          console.log('buildStart');
        },
        // vite特有钩子
        config(config) {
          console.log('config', config);
          return {}
        },
        configResolved(resolvedCofnig) {
          console.log('configResolved');
        },
        configureServer(server) {
          console.log('configureServer');
          // server.app.use((req, res, next) => {
          //   // custom handle request...
          // })
        },
        transformIndexHtml(html) {
          console.log('transformIndexHtml');
          return html
          // return html.replace(
          //   /<title>(.*?)<\/title>/,
          //   `<title>Title replaced!</title>`
          // )
        },
        // 通用钩子
        resolveId ( source ) {
          if (source === 'virtual-module') {
            console.log('resolvedId', source);
            return source; 
          }
          return null; 
        },
        load ( id ) {
          if (id === 'virtual-module') {
            console.log('load');
            return 'export default "This is virtual!"';
          }
          return null;
        },
        transform(code, id) {
          if (id === 'virtual-module') {
            console.log('transform');
          }
          return code
        },
      };
    }
    

    钩子调用顺序

    精通Vite2之插件开发指南

    插件顺序

    • 别名处理Alias
    • 用户插件设置enforce: 'pre'
    • Vite核心插件
    • 用户插件未设置enforce
    • Vite构建插件
    • 用户插件设置enforce: 'post'
    • Vite构建后置插件(minify, manifest, reporting)

    精通Vite2之插件开发指南

    插件编写实操

    实现一个mock服务器vite-plugin-mock

    实现思路是给开发服务器实例(connect)配一个中间件,该中间件可以存储用户配置接口映射信息,并提前处理输入请求,如果请求的url和路由表匹配则接管,按用户配置的handler返回结果。

    精通Vite2之插件开发指南

    创建plugins/vite-plugin-mock.js

    import path from 'path'
    
    let mockRouteMap = {};
    
    function matchRoute(req) {
      let url = req.url;
      let method = req.method.toLowerCase();
      let routeList = mockRouteMap[method];
    
      return routeList && routeList.find((item) => item.path === url);
    }
    
    function createRoute(mockConfList) {
      mockConfList.forEach((mockConf) => {
        let method = mockConf.type || 'get';
        let path = mockConf.url;
        let handler = mockConf.response;
        let route = { path, method: method.toLowerCase(), handler };
        if (!mockRouteMap[method]) {
          mockRouteMap[method] = [];
        }
        console.log('create mock api: ', route.method, route.path);
        mockRouteMap[method].push(route);
      });
    }
    
    function send(body) {
      let chunk = JSON.stringify(body);
      // Content-Length
      if (chunk) {
        chunk = Buffer.from(chunk, 'utf-8');
        this.setHeader('Content-Length', chunk.length);
      }
      // content-type
      this.setHeader('Content-Type', 'application/json');
      // status
      this.statusCode = 200;
      // respond
      this.end(chunk, 'utf8');
    }
    export default function (options = {}) {
      options.entry = options.entry || './mock/index.js';
    
    
      if (!path.isAbsolute(options.entry)) {
        options.entry = path.resolve(process.cwd(), options.entry);
      }
    
      return {
        configureServer: function ({ app }) {
          const mockObj = require(options.entry);
          createRoute(mockObj);
    
          const middleware = (req, res, next) => {
            let route = matchRoute(req);
    
            if (route) {
              console.log('mock request', route.method, route.path);
              res.send = send;
              route.handler(req, res);
            } else {
              next();
            }
          };
          app.use(middleware);
        },
      };
    }
    

    视频教程

    除了以上基础内容之外,我还录制了vite-plugin-vue-i18n源码学习视频,包括国际化插件的安装、使用、原理和手写实现,精彩异常,欢迎小伙伴们来捧场: 【备战2021】Vite2插件开发指南「持续更新中」

    原创不易,欢迎各位小伙伴三连+关注,您的鼓励是我坚持下去的最大动力❤️

    配套源码

    欢迎关注公众号村长学前端自取

    后续创作计划

    Vite为什么这么快,它能不能顶替webpack现在在前端的地位哪?我想小伙伴们一定和我一样有这样的疑问,后续我打算搞一搞Vite原理的剖析,并最终手写一个我们自己的Vite来。大家点个赞?,关注一下,以便后续学习。


    起源地下载网 » 精通Vite2之插件开发指南

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元