聊聊前端项目构建的现状与想法

由来
经过近几年的沉淀,前端届的变革在现阶段总算是进入了一个平稳期。回顾一下前人走过的路,主要是在解决以下问题:

浏览器支持的语言特性不太友好,影响开发效率
项目缺乏依赖管理,复制粘贴太低效且不好控制
需要工具来压缩代码、压缩图片、生成文件hash用于控制浏览器缓存等功能
开发时保存代码能实时刷新浏览器提高开发体验

为了解决这些问题,出现了以下解决方案:

babel,将ES6、typescript转成浏览器支持的ES5代码
DSL(domain specific language),例如:less、sass等对于css的扩展,jsx、vue template、angular template对于html的扩展
npm 依赖管理工具
利用工具处理压缩代码、压缩图片、生成文件hash等功能
利用live reload、browsersync、hot reload工具实时刷新浏览器

这些解决方法成为了我们开发中不可或缺的功能,于是我们需要一个工具把这些联立起来,于是前后出现像grunt、gulp、fis、webpack等前端工程化构建工具。经过一段时间的更新迭代后,webpack以万物皆模块的思想以及功能强大,渐渐在众多工具中脱颖而出,成为前端项目中常用的构建工具。
现状
在现阶段,个人觉得前端项目构建越来越重、越来越繁琐了。对于一个新的项目,总是需要安装一堆的依赖(几百M的node_modules),然后写一堆构建工具的配置项,最后才能进行业务开发。当项目越来越大的时候,每次启动时都需要花费不少时间。因为构建工具需要对项目进行依赖分析、编译,最后才能输出浏览器能执行的文件。这时构建工具配置的优化又提上大家的工作日程。
目前构建优化的方案,以webpack为例,主要有以下几个方向:

减轻依赖分析:webpack的resolve配置,loder的exclude配置
分包,动态加载:import()、require.ensure()
提取公用部分,减少需要编译的依赖项:DllPlugin、externals
利用多线程、多进程进行并行编译:thread-loader、happyPack
缓存:cache-loader、hard-source-webpack-plugin

但是业务代码到达一定程度(5W行以上),做了上述的优化后,速度确实加快了不少,但是个人感觉对于dev(开发环境)仍然有些沉重。
想法
在某次看到@vue/dev-server这个工具后,突然间灵光一闪,想到了一个可行性的方案。这个工具只用一行命令就可以快速的启动一个.vue 单文件的开发环境,我们先来看看它做了什么处理。
按照文档建立的的文件,没有webpack.config之类的配置,也没有预处理输出的文件。

index.html 文件,利用目前最新chrome浏览器支持的es module加载main.js。

Vue dev
复制代码main.js文件,引入test.vue文件,跟平常项目的入口文件一样。test.vue文件内代码就是平常vue单文件的格式,不展示了。 import Vue from 'vue' import App from './test.vue'

new Vue({
render: h => h(App)
}).$mount(’#app’)
复制代码接着来看看浏览器加载的资源,路径跟import保持一致,类型都是script(Content-Type: application/javascript)。

main.js中,import Vue from 'vue’被处理成import Vue from ‘/__modules/vue’。因为浏览器的es module还未实现仍在提案的import-maps特性,所以不支持不带路径的依赖。vue就是浏览器能执行的vue.js。

test.vue就是源文件进行编译之后的代码,因为原本的.vue单文件浏览器是不支持的,需要进行预编译。

由此可见,该工具重点在于利用中间件,做了以下处理:

转换不带路径的依赖(暂时只是vue,其它npm包未处理)的引用地址,让浏览器支持
预编译.vue文件,转换成浏览器支持的js,类似于webpack中的vue-loader

仔细思考一下,目前的构建工具都是对项目所依赖的资源文件进行全量的处理,但很多时候,我们只是对于某个页面中的某个模块进行开发。从理想的角度出发,其实我们只需要对该页面依赖的资源文件进行处理。每当加载浏览器不能执行的资源:vue、sass、less等,才进行转译/编译处理,最后输出资源文件到浏览器。
实际上社区也有人在做类似的尝试,比如:systemjs,github描述是:Dynamic ES module loader。当然这不只是为了在浏览器端兼容es module,重点在于其实现的Transform loader功能。该功能提供类似于webpack loader的功能,对于匹配的依赖进行相对应的loader处理。具体loader处理可以放到web worker或者通过node server进行处理,如果能兼容大部分webpack loader倒是一个不错的方案。
目前该想法还有待验证与实现,有兴趣的可去了解一下相关的内容,若有进一步的研究,也希望能一起交流讨论。

你可能感兴趣的:(聊聊前端项目构建的现状与想法)