webpack与项目构建再认识
webpack 这个工具在前端社区异常的流行,以至于我在一年前就简单的研究过,当时发现webpack在无意中提出了「Web模块」的概念——任何web app组成都可以是模块(JS模块是一种),对其进行依赖跟踪,当在发布时可解释最新依赖后打包出最新版本。「Web模块」的概念确让人耳目一新,不过由于一直没有参加具体商业项目,对 Wepback 没有多少经验,也谈不上有太深刻的认识(包括本质和意义)。
最近正在着手做一些实验项目,开始触及项目构建。读了《Setting up an ES6 Project Using Babel and webpack》,发现 webpack 的目标就是 给现代JS项目开发引入 构建 一步( introduce a build step into your process),这个观点我觉得很关键,和深刻。
webpack 与 现代web项目开发流程
最初的JS项目开发是比较简单的,纯手工,开发和构建(编译)混在一起。但显然,当项目规模增大,手工需要转向自动化。 然而,什么东西需要自动化呢?这个问题针对JS项目(Web程序结构很复杂),初学者具有异常的困难。所以学习使用 wepback 一开始是不容易的。
首先明白一点,编译(将一种码转为另一种码)只是构建的一步,模块打包也是一步而已,而自动化构建的具体任务(WHAT)和过程顺序(ORDER),根据项目性质的不同,工作流(WORKFLOW)不同会有不同。例如,项目使用了不同CSS架构方法,那「CSS样式开发」的流程就会不同。
印象中 wepback 只是实现的模块管理系统——让开发者使用import等语句(包括import图片资源),因为wepback 声称是一个 module bundler (模块打包器),与 bable(E6+)编译器是相对独立的。 然而,bable成了Wepback构建的一步,可见,Wepback的“野心”不小。
Webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.
EM:module bundler 划小它的属涵义了,webpack的「属概念」是构建的中心工具,甚至代表了构建本身了。
这也是我觉得 「 wepback 的目标就是 给现代JS项目开发引入 构建 一步」,这个观点很关键,wepback尝试 为JS 项目开发提供一个抽象平台,开发者可以在这个平台上使用种种现代工具(ES6+ TS ESM CSSM等),非常高效的工作,其它麻烦活(浏览器厂商兼容,ES版本兼容,Web模块依赖等)都可以配置好后,wepback自动化处理。这个思想非常的好。
初步研究,wepback通过几个思想实现它的伟大目标:
- 第一,「Web模块」;包括JS模块,CSS模块,图片资源类模块等;「模块」是有依赖关系的程序有机组成;
- 第二,转换加载器,将抽象的模块转换为 合格的「Web模块」,例如ts loader,babel loader,file loader, css loader等;
- 第三,插件;模块打包以外的构建任务,例如数据优化,压缩,lint等;
从逻辑和历史发展上认识 webapck
由于webpack的愿景比较宏大,认识 webpack 不能简单从它作为构建工具这一单一角度去认识 它的工具性,应该从,第一,从整个前端生态(包括历史)确定 webpack的角色;第二,从一个完整的 前端商业项目上看 webpack的角色。
从历史发展看 webpack,JS和项目构建任务
JavaScript 和其它大多数 web 开发技术 一样,一直在不断演化。在过去,我们只需要 页面上 放一些< script > 标签,这些标签可能有 jQuery 和一些插件,程序就可以跑起来了。
然而,自从推出ES6,事情变得越来越复杂。各大浏览器对ES6新语言特性支持参差不齐(需要转译后向兼容),JS应用规模增大需要进行模块化等等。这些意味着,如果你想 使用现代版JS 进行开发,你得需要给你的开发工作流中增加 构建 一项(need to introduce a build step into your process)。
所谓增加 构建 一项是指,为项目创建一个构建系统,此系统为开发者提供一个工作平台,开发者使用最新工具,专心关注功能的实现,剩下的代码生成任务由「构建系统」自动完成。构建系统的任务一般包括,转译(transpiling),编译CSS,打包web模块,压缩和优化代码等任务。
这里最关键的是,构建系统提供简单的几个命令接口自动执行这些任务。
从逻辑上看 webpack
webpack 是一支 打包JS程序模块(Web模块)的node 工具包,webpack和npm ,node ,构建系统和 JS在逻辑上有着错综复杂的关系。
构建系统 和 webpack的关系
第一,当我们说 构建系统 ,在前端社区,一般默认 是「构建web app 」并且「使用 node.js作基础技术」的 Web 构建系统;因为,构建系统 可构建其它种类应用程序,也可以别的基础技术;
第二,构建系统 可以有不同的构建任务(使用 npm -D 安装 构建工具),构建任务有,编译,打包,测试,优化,发布部署等;
第三,webpack 只是其中最为流行的一支 构建工具;反过来,当我们说研究webpack时,也就知道,它是实现「一种 构建系统」;
node 项目 和webpack的关系
webapck 和「node 项目」(就是源码项目的根目录)有这样的一些结构关系:
首先,使用 npm init -y 创建的都是node 项目,不同的node 项目可安装(npm install -D)不同的 构建工具 或辅助工具,webapck只是其中一个;
其次,任何 「web app项目」都是 一个 node项目,一个很特殊的node app,用来辅助制作 web app这个结论和事实很容易被忽略;因为它用到了npn init -y 和 package.json 。
第三,「web app项目」只是 「node项目」的一个目录部分,例如 /src,认清这个区别就是明白npm install --save和 --save-dev 的意义;
npm install --save:为源码项目添加功能依赖,可以直接import xxx from 'libxxx',引入模块
npm install --save-dev:为构建系统添加 新构建工具,可在package.json或其它node工具的配置上安装执行
第四, 「 node 项目」是一个webapck式构建系统,使用 webapck,有webpack.config.js;
第五,webapck会配置 loader 和 plugin,完成其他构建任务;
JS , TS , webpack , babel , React 之间的关系
它们都是在现代JS Dev workflow 上添加了环境抽象(npm使用 -D安装),从反例看,
- 没有babel就没法用 箭头函数和asyn函数,不安装Webpack不能使用import,
- 不添加TS 就不能用 Interface (接口)数据类型,不import React lib 就不能用 Hooks(useState)
正面看,
- babel 搭建了 ES6 ES7 ES NEXT 编码环境;
- webpack 搭建了 Web 模块系统,包括 JS 图片 CSS等资源模块;
- TS 和babel比较像,搭建了强类型 编码环境;
- React 则是应用库,搭建了 UI 工具库;当然,它的JSX还是由babel来搭建;
- JS 就是直接在浏览上运行,代码ES5
总结
总的来说,为了支持现代式开发(包括 ES6+ TS ESM VDOM),构建系统以 webpack作为中心构建工具;Web项目,NPM,Node,webpack等有如下的关系:
现代程序项目 L 现代Web 项目(使用 node npm作基础技术,使用npm init -y创建,有package.json) L 构建系统(提供抽象的现代编程环境,ES6+ ESM TS CSSM;使用npm intall -D 安装构建工具) L webpack式构建系统(node tool) L 模块打包 L JS模块打包 E CSS 模块打包 E 其它静态资源模块打包 E 其它构建任务 E Web项目(本身,也是node 项目,使用npm install -save的库) E 版本管理
第一,流行的JS项目构建系统使用npm,Node作为基础技术;JS项目实质一个特殊的Node app;
第二,现代Web项目由 构建系统、Web项目源码、功能测试系统和版本管理等「子系统」组成;同位于< ROOT >根目录之内;
第三,构建系统为开发者提供了现代开发环境,使用webpack作为工具;
第四,构建系统的构建任务包括了模块打包,和其他构建任务;
最后,「开发」(或程序开发)是一个专注解决业务需求,对其进行分析,使用特定工具,制作出满足需求的产品(功能)的过程。「现代JS 项目开发」需要构建系统,因为它那“构建”的一步提供了一个抽象平台,提供最新最有效率的工具,让开发者专心高效的工作。