diff --git a/published/20230216.2 ⭐️⭐️ Writing Javascript without a build system.md b/published/20230216.2 ⭐️⭐️ Writing Javascript without a build system.md new file mode 100644 index 0000000000..cafee37959 --- /dev/null +++ b/published/20230216.2 ⭐️⭐️ Writing Javascript without a build system.md @@ -0,0 +1,195 @@ +[#]: subject: "Writing Javascript without a build system" +[#]: via: "https://jvns.ca/blog/2023/02/16/writing-javascript-without-a-build-system/" +[#]: author: "Julia Evans https://jvns.ca/" +[#]: collector: "lkxed" +[#]: translator: "wxy" +[#]: reviewer: "wxy" +[#]: publisher: "wxy" +[#]: url: "https://linux.cn/article-15666-1.html" + +在没有构建系统的情况下编写 Javascript +====== + +![][0] + +嗨!这周我一直在写一些 Javascript,和往常一样,当我开始一个新的前端项目时,我面临的问题是:我是否应该使用构建系统? + +我想谈谈构建系统对我有什么吸引力,为什么我(通常)仍然不使用它们,以及一些前端 Javascript 库要求你使用构建系统时,为什么我觉得这让我感到沮丧。 + +我写这篇文章是因为我看到的大多数关于 JS 的文章都假定你正在使用构建系统,而对于像我这样的人来说,编写非常简单的、不需要构建系统的小型 Javascript 项目时,构建系统可能反而添加了很多麻烦。 + +#### 什么是构建系统? + +构建系统的思路是,你有一堆 Javascript 或 Typescript 代码,你想在把它放到你的网站上之前把它翻译成不同的 Javascript 代码。 + +构建系统可以做很多有用的事情,比如: + +- (出于效率的考虑)将 100 多个 JS 文件合并成一个大的捆绑文件 +- 将 Typescript 翻译成 Javascript +- 对 Typescript 进行类型检查 +- 精简化 +- 添加 Polyfills 以支持旧的浏览器 +- 编译 JSX +- 摇树优化Tree Shaking(删除不使用的 JS 代码以减少文件大小) +- 构建 CSS(像 [tailwind][1] 那样) +- 可能还有很多其他重要的事情 + +正因为如此,如果你今天正在构建一个复杂的前端项目,你可能会使用 Webpack、Rollup、Esbuild、Parcel 或 Vite 等构建系统。 + +很多这些功能对我很有吸引力,我过去使用构建系统也是出于这样一些原因: 例如,[Mess With DNS][2] 使用 Esbuild 来翻译 Typescript,并将许多文件合并成一个大文件。 + +#### 目标:轻松地对旧的小网站进行修改 + +我做了很多简单的小网站([之一][3]、[之二][4]、[之三][5]、[之四][6]),我对它们的维护精力大约为 0,而且我改变它们的频率很低。 + +我的目标是,如果我有一个 3、5 年前做的网站,我希望能在 20 分钟内, + +- 在一台新的电脑上从 GitHub 获取源代码 +- 做一些修改 +- 把它放到互联网上 + +但我对构建系统(不仅仅是 Javascript 构建系统!)的经验是,如果你有一个 5 年历史的网站,要重新构建这个网站会非常痛苦。 + +因为我的大多数网站都很小,所以使用构建系统的 *优势* 很小 —— 我并不真的需要 Typescript 或 JSX。我只要有一个 400 行的 `script.js` 文件就可以了。 + +#### 示例:尝试构建 SQL 实验场 + +我的一个网站([SQL 试验场][5])使用了一个构建系统(它使用 Vue)。我最后一次编辑该项目是在 2 年前,是在另一台机器上。 + +让我们看看我今天是否还能在我的机器上轻松地构建它。首先,我们要运行 `npm install`。下面是我得到的输出: + +``` +$ npm install +[lots of output redacted] +npm ERR! code 1 +npm ERR! path /Users/bork/work/sql-playground.wizardzines.com/node_modules/grpc +npm ERR! command failed +npm ERR! command sh /var/folders/3z/g3qrs9s96mg6r4dmzryjn3mm0000gn/T/install-b52c96ad.sh +npm ERR! CXX(target) Release/obj.target/grpc/deps/grpc/src/core/lib/surface/init.o +npm ERR! CXX(target) Release/obj.target/grpc/deps/grpc/src/core/lib/avl/avl.o +npm ERR! CXX(target) Release/obj.target/grpc/deps/grpc/src/core/lib/backoff/backoff.o +npm ERR! CXX(target) Release/obj.target/grpc/deps/grpc/src/core/lib/channel/channel_args.o +npm ERR! CXX(target) Release/obj.target/grpc/deps/grpc/src/core/lib/channel/channel_stack.o +npm ERR! CXX(target) Release/obj.target/grpc/deps/grpc/src/core/lib/channel/channel_stack_builder.o +npm ERR! CXX(target) Release/obj.target/grpc/deps/grpc/src/core/lib/channel/channel_trace.o +npm ERR! CXX(target) Release/obj.target/grpc/deps/grpc/src/core/lib/channel/channelz.o +``` + +在构建 `grpc` 时出现了某种错误。没问题。反正我也不需要这个依赖关系,所以我可以花 5 分钟把它拆下来重建。现在我可以 `npm install` 了,一切正常。 + +现在让我们试着构建这个项目: + +``` +$ npm run build + ? Building for production...Error: error:0308010C:digital envelope routines::unsupported + at new Hash (node:internal/crypto/hash:71:19) + at Object.createHash (node:crypto:130:10) + at module.exports (/Users/bork/work/sql-playground.wizardzines.com/node_modules/webpack/lib/util/createHash.js:135:53) + at NormalModule._initBuildHash (/Users/bork/work/sql-playground.wizardzines.com/node_modules/webpack/lib/NormalModule.js:414:16) + at handleParseError (/Users/bork/work/sql-playground.wizardzines.com/node_modules/webpack/lib/NormalModule.js:467:10) + at /Users/bork/work/sql-playground.wizardzines.com/node_modules/webpack/lib/NormalModule.js:499:5 + at /Users/bork/work/sql-playground.wizardzines.com/node_modules/webpack/lib/NormalModule.js:356:12 + at /Users/bork/work/sql-playground.wizardzines.com/node_modules/loader-runner/lib/LoaderRunner.js:373:3 + at iterateNormalLoaders (/Users/bork/work/sql-playground.wizardzines.com/node_modules/loader-runner/lib/LoaderRunner.js:214:10) + at iterateNormalLoaders (/Users/bork/work/sql-playground.wizardzines.com/node_modules/loader-runner/lib/LoaderRunner.js:221:10) + at /Users/bork/work/sql-playground.wizardzines.com/node_modules/loader-runner/lib/LoaderRunner.js:236:3 + at runSyncOrAsync (/Users/bork/work/sql-playground.wizardzines.com/node_modules/loader-runner/lib/LoaderRunner.js:130:11) + at iterateNormalLoaders (/Users/bork/work/sql-playground.wizardzines.com/node_modules/loader-runner/lib/LoaderRunner.js:232:2) + at Array. (/Users/bork/work/sql-playground.wizardzines.com/node_modules/loader-runner/lib/LoaderRunner.js:205:4) + at Storage.finished (/Users/bork/work/sql-playground.wizardzines.com/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:43:16) + at /Users/bork/work/sql-playground.wizardzines.com/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:79:9 +``` + +[这个 Stack Overflow 的答案][7] 建议运行 `export NODE_OPTIONS=--openssl-legacy-provider` 来解决这个错误。 + +这很有效,最后我得以 `npm run build` 来构建这个项目。 + +这其实并不坏(我只需要删除一个依赖关系和传递一个略显神秘的 Node 选项!),但我宁愿不被那些构建错误破坏。 + +#### 对我来说,对于小项目来说,构建系统并不值得 + +对我来说,一个复杂的 Javascript 构建系统对于 500 行的小项目来说似乎并不值得 —— 它意味着放弃了在未来能够轻松更新项目的能力,以换取一些相当微小的好处。 + +#### Esbuild 似乎更稳定一些 + +我想为 Esbuild 大声叫好: 我 [在 2021 年了解到 Esbuild][8],并用于一个项目,到目前为止,它确实是一种更可靠的构建 JS 项目的方式。 + +我刚刚尝试在一台新电脑上构建一个我最后一次改动在 8 个月前的 Esbuild 项目,结果成功了。但我不能肯定的说,两年后我是否还能轻松的建立那个项目。也许会的,我希望如此! + +#### 不使用构建系统通常是很容易的 + +下面是 [Nginx 实验场][6] 代码中导入所有库的部分的样子: + +``` + + + + + + + +``` + +这个项目也在使用 Vue,但它只是用 ` - - - - - - -``` - -This project is also using Vue, but it just uses a `