JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

框架到底做了什么

在你拿起 React、Django 或 Rails 之前,先搞懂它们底下那个简单的道理——一套现成的脚手架,它会来调用你的代码,让你不必从零造一切。

问题所在:你总在重复搭同样的管道

想象你要做一个小网站,让人能注册、登录、发消息。单看每一项都不吓人。可在你写下第一行有意思的代码之前,你会发现前面堆着一座又枯燥又琐碎的活儿:接住网络请求、弄清楚对方要的是哪个页面、核对密码、跟数据库打交道、再把正确的 HTML 发回去。地球上每一个应用都需要这同一套管道。

麻烦在于,这套管道不仅写起来无聊——它还很容易出现细微的错误,而且到了下一个项目你又得从头再写一遍。这是大量被浪费的精力,也是大量在「跟你真正在乎的想法毫无关系」的代码里埋下 bug 的机会。

框架是一套现成的脚手架

框架(framework)就是那条面包。它是为一整类应用预先搭好的大骨架,所有枯燥的管道都已经替你写好、测好、安排妥当。React 是在浏览器里搭界面的框架;Django(Python)和 Rails(Ruby)则是搭网站服务端的框架。你挑一个,那又难又重复的 80% 一下子就「现成在那儿了」。

下面这一点能让你瞬间「懂」框架,而它一开始几乎让所有人意外:是框架来调用你的代码——不是你去调用它。当你写一个普通的小工具函数并使用它时,你是老板:什么时候运行由你说了算。换成框架,角色就反过来了。框架才是老板。整场演出由它主导,到了恰当的时刻它会转头问你:「有用户刚刚要看首页——我该给他们显示什么?」你把答案递给它,它再接手继续跑。

# YOU just fill in the blank.
# The framework decides WHEN to call this.
def home_page(request):
    return "Hello, world!"
你只写一小块(首页显示什么);其余的归框架,访客一来它就调用你。

框架不会单独前来:依赖

框架很少独自前来。为了干好活,它会倚靠许多更小的、别人写好的代码块——一个处理日期的工具、一个跟数据库对话的、一个安全核对密码的。每一个这样的东西都是一个依赖(dependency):你的项目「依赖」它、但并不是你自己写的代码。一个真实的应用轻轻松松就会倚靠上百个依赖,其中大多数你永远不会直接去看。

靠手工去下载并追踪上百个零件简直是噩梦,所以这件事你交给包管理器(package manager)来做。你把想要的东西的名字列下来——在 JavaScript 里这份清单写在一个文件里,然后你运行一条像 `npm install` 这样的命令——包管理器就会把每一个都取回来,连同「它们」各自依赖的东西一起,妥妥地塞进你的项目。一条命令,整条供应链就办妥了。

npm install react
一行命令,让包管理器把 React 以及 React 自身运行所需的一切都取回来。

打包工具把这一切打包好去运行

现在你有了一种「太多」的烦恼。你的应用散落在你自己的文件、外加上百个依赖文件里,而它们没法原样直接送进浏览器(browser)——浏览器要一个一个去要上千个小文件会慢得让人难受,而且开发者写的一些现代简写它还看不懂。这时候就轮到打包工具(bundler)出场了。

打包工具就像搬大家之前的打包服务。它走遍你所有的代码和依赖,弄清楚到底哪些是真正用到的,把现代简写翻译成浏览器看得懂的普通代码,再把一切压进区区几个整洁的文件里。这几个最终文件,就是被送进运行时(runtime)的东西——运行时就是浏览器内部那台真正执行你程序的引擎。

  1. 它从你的主文件出发,顺着每一个依赖走,画出一张「到底哪些真用到」的地图。
  2. 它把现代的或特殊的写法,翻译成每个浏览器都能读的普通代码。
  3. 它扔掉用不到的部分,再把剩下的压小。
  4. 它输出区区几个最终文件,随时可以被浏览器加载并运行。

这里的取舍是真实的,值得点明。打包工具会多出一道构建步骤(build step):一个夹在「写代码」和「看它跑起来」之间的环节,意味着要多配置一些工具,而且你每改一处都要等上一会儿。作为交换,你得到的是加载飞快的页面、浏览器可靠看得懂的代码,以及自由使用那一大堆顺手依赖的权利。除了那种极小的页面,这笔买卖几乎总是划算的——而且现代框架通常已经替你把打包工具配好,让你几乎感觉不到这份代价。

把这一切串起来

于是一口气把整幅图景说完。你不会从零造一个网页应用——你站在一个框架上,那是一套现成的脚手架,已经把无聊的 80% 处理好,需要你那份具体答案时才礼貌地来调用你的代码。这个框架倚靠着许多依赖,而包管理器用一条命令就替你把它们取回来、追踪好。

最后,打包工具把这一切——你的代码加上每一个依赖——收拢起来,打包成几个整洁的文件,让浏览器里的运行时能真正运行它,用多出的那一道构建步骤换来速度与便利。这些环节没有一个是魔法。它们每一个的存在,都是为了让你不必重写同样的管道,好让你的精力流向它真正该去的地方:那个只有你才造得出来的部分。