Zong
牛气冲天

荣获 2020 年度优秀员工

年度总结

入职公司近 1 年时间,真的收获了许多,感谢所有帮助过我的大佬,感谢努力的自己。

业务交付

完成基本的 B 端业务交付工作,包括开发、联调对接、缺陷修复、人员安排、项目管理、技术支持、新人培养。

在这一年中,新接触了一些关于管理方面的工作,保障业务按时交付的情况下,也带着同事们一起提炼一些经验。

比如和同事们一起提炼了 TypeScript 实践经验手册,供其他同事学习。

再者就是下发给同事的抽象能力挑战,提供有效的指导,帮助同事在有限的时间内完成代码抽象及封装。

技术贡献

技术贡献一直是我在工作中自产的一些挑战任务,为了让工作更有挑战性。

  • 来自一些业务交付时所产生的挑战,包括对现有库的缺陷修复、新特性支持、定制特性支持。
  • 业务交付过程中解耦出的通用型组件库、 SDK 。
  • 在代码中运用合理的设计模式来抽象代码、优化代码设计,提供更易维护、更易阅读、更易使用的代码模块。
  • 参与微前端架构设计及调整,涉及开发、构建、 CI/CD (一件很有挑战的事)。

TypeScript 推进

  • 推进内部 TypeScript 使用
  • 总结 TypeScript 实践经验

标准代码风格

因为经历了多个业务交付,发现不同业务的代码风格稍有不同,考虑到为了统一风格,则邀请多位同事一同讨论,抽离现有合理规则,定制内部标准。

从而在年底发布内部标准代码风格,支持 JavaScript / TypeScript / Node / Vue 。

学习 TC39 工作组记录会议纪要。

单元测试

单元测试的编写附属于技术贡献时,以保证代码的稳定性。

  • 内部库的单元测试,保证覆盖率 70%+
  • 运用设计模式的抽象代码,提供单元测试

技术分享

共计 2 场技术分享

  1. 《TypeScript 给我们带来了什么》
  2. 《追求优雅的代码》

人才招聘

负责部门实习生、社招岗位一二面。(面试 20 人左右,入围 5 人左右,具体记不清了,不重要)

在面试过程中,我也在学习,从候选人的身上寻找自己的不足。

比如在面试 CSS 方面,因为我 CSS 方面并不是特别的擅长,所以会需要资料和同事的协助。

我也明白了,我需要如何系统的学习 CSS ,才能凸显我掌握了 CSS 。

所以当在面试 CSS 相关的知识时,可以从各个 CSS Level 级别去阐述 CSS 特性。(这点很重要)

当然,另外的就是前端的基础掌握程度。(这点也很重要)

虽然面试很吃时间,但是或多或少是可以学习到不少东西的,要保持这种心态。

复盘

这一年,很不错!

比较遗憾的是,没有足够的时间去尝试:

  • 可视化
  • 工程化
  • 服务端

对于未来的工作规划似乎又有了一些新的想法:

  • 继续拓展软件开发领域知识广度
  • 尝试可能性
  • 现在选择一条路走到底还早

工程化探索

恭喜同桌大佬进入蚂蚁金服,向大佬学习的心日益强烈!

春节前除了保证业务的正常交付,开始交接工程化相关的项目,慢慢开始介入 CI/CD 相关工作。

其实发现关于前端工程化 + CI 形成前端自动工程化与 CD 组合是一件很富有挑战性的工作。

光前端工程化就有很多库、知识可以学习,非常的兴奋。

CI/CD 则会与服务端的同学进行配合,同时又可以学习到服务端的相关知识,慢慢的对服务端也有更多的了解和认识。

在维护 Webpack 插件时,利用 Dynamic Public Path Plugin 的思路解决现有 publicPath 存在的问题。

因为是一个微前端架构的 SPA 工程打包为多页面的工程思路,配合后端路由寻址,所以 publicPath 需要为动态,刚好这个开源的插件给我了灵感:

'use strict';

class WebpackDynamicPublicPath {

    /**
     *
     * @param {Object} options
     * @param {string} options.externalPublicPath - variable with new publicPath
     * @param &#123;Array<string>&#125; [options.chunkNames] - list of chuck names in which publicPath will be replaced,
     * in case if parameter is not defined publicPath will be replaced for all chunks
     */
    constructor(options) &#123;
        this.options = options;

        this.afterPlugins = this.afterPlugins.bind(this);
        this.emit = this.emit.bind(this);
    &#125;

    apply(compiler) &#123;
        compiler.hooks.afterPlugins.tap(&#123;name: 'WebpackDynamicPublicPath'&#125;, this.afterPlugins);
        compiler.hooks.emit.tapPromise(&#123;name: 'WebpackDynamicPublicPath'&#125;, this.emit);
    &#125;

    afterPlugins(compilation) &#123;
        if (typeof compilation.options.output === 'undefined' || typeof compilation.options.output.publicPath === 'undefined') &#123;
            throw new Error('WebpackDynamicPublicPath: params missing - output.publicPath must be defined in webpack config (used only as placeholder, make it distinctive)');
        &#125;

        if (typeof this.options === 'undefined' || typeof this.options.externalPublicPath === 'undefined') &#123;
            throw new Error(`WebpackDynamicPublicPath: params missing - externalPublicPath - name of global variable you want to use as publicPath.`);
        &#125;

        this.publicPath = `"$&#123;compilation.options.output.publicPath&#125;"`;
    &#125;

    emit(compilation) &#123;
        const chunks = this.options.chunkNames ?
            compilation.chunks.filter(chunk => this.options.chunkNames.includes(chunk.name)) :
            compilation.chunks;

        if (!chunks.length) &#123;
            throw new Error('WebpackDynamicPublicPath: chunks array for replacing publicPath is empty.');
        &#125;

        const fileNames = chunks.map(
            chunk => chunk.files.find(
                file => file.match(/.*\.js/)
            )
        );

        const replacePromises = fileNames.map(fileName => this.replacePublicPath(fileName, compilation));

        return Promise.all(replacePromises).then(() => console.log('WebpackDynamicPublicPath: publicPath replaced.'));
    &#125;

    /**
     * Replace publicPath
     * @param &#123;string&#125; fileName
     * @param &#123;object&#125; compilation
     * @return &#123;Promise<any>&#125;
     */
    replacePublicPath(fileName, compilation) &#123;
        return new Promise((resolve) => &#123;
            const source = compilation.assets[fileName].source();
            const publicPath = this.publicPath;
            const externalPublicPath = this.options.externalPublicPath;

            compilation.assets[fileName].source = function () &#123;
                return source.replace(publicPath, externalPublicPath);
            &#125;;

            resolve();
        &#125;);
    &#125;
&#125;


module.exports = WebpackDynamicPublicPath;

源码很简单,我就复制过来凑凑字数,内部的细节我就不做展示,逻辑我在这里介绍一下。

利用环境变量配置,提供公共的 publicPath 前缀,获取需要被拆分的页面模块名称,拼接特定的 publicPath 内容。