<output id="ilehw"><bdo id="ilehw"><nobr id="ilehw"></nobr></bdo></output>
        <dl id="ilehw"><font id="ilehw"></font></dl>
          1. 用 Bazel 构建 TypeScript 项目 已翻译 100%

            oschina 投递于 01/14 19:05 (共 9 段, 翻译完成于 01-25)
            阅读 452
            收藏 1
            2
            加载中

            在本篇,我会简单介绍一下Bazel是什么,我们怎么用它构建一个Typescript项目。如果你已经熟知Bazel解决什么问题,那么请跳到“用Bazel构建Typescript”一节。你可以在我的Github上找到例子!

            Google's 集成内幕

            谷歌管理着无数的源码。在每个独立项目间都有依赖,比如Google Cloud 依赖于 Angular & Angular Material,Angular Material 又依赖于 Angular, 最后它们?#23478;?#36182; TypeScript.

            在谷歌中,项目都有使用独立库(以及第三方库)的版本号。在公司内,这极大的简化了依赖管理。同时升级一个库,能影响所有依赖的项目,这样很方便。这样每个人都能从中得到好处,比如最新的安全更新,?#38405;?#20248;化,Bug修复。这样做就意味着微软发布新的Typescript, 它会尽快的同步到谷歌内部,可以想你,Typescript的破坏性变更会影响许多代码!

            为了验证库升级后没?#24615;?#26469;代码,在内部的?#20013;?#38598;成中需要重新构建所有的依赖项目,并执行相应测试。因为有无数的TS文件,无数行TS代码,如果把控不好,整个过程可能需要点时间。

            多数情况,项目依赖其它项目,比如Google Cloud依赖它的UI和后端服务。当只更新Typescript时,既然后台服务不依赖Typescript,我们不希望它重新构建后台服务!

            noonoo
            noonoo
            翻译于 01/23 17:13
            0

            Bazel是什么

            为了构建项目,谷歌开源了这个Bazel工具。它是一个强大的工具,它可以跟踪不同的包间的依赖,并构建目标。简单说,一个构建就是一个构建规则,比如: “构建一下Typescript库”;  从项目看,一个包对应着一个文件夹中的许多文件,它有清晰的依赖包。在Google Cloud的示例中,Bazel会对应下面这么一个依赖关系图:

            简单说,我?#21069;?#19978;图每一个块都对应一个构建目标。当其中某个块变化,Bazel会计算哪些包直接或间接依赖于它,并构建它们。在上面例子,如果TypeScript变化了,它会构建除了 back-end services之外?#30446;欏?/p>

            下面是Bazel?#30446;?#30340;特性:

            1、它有一个聪明的算法来计算依赖

            2、它有独立的技术栈。你可以用同样的接口构建?#25105;?#30340;事情。就像,已经?#34892;?#22810;它的插件来服务于:Java,Go,Typescript,Javascript等等。

            noonoo
            noonoo
            翻译于 01/23 17:29
            0

            我们先看看第一条,基于一个项目的依赖图,Bazel会判断哪些构建目标是可以并行处理。但这个特性只在单元测试已经很好的定义了输入项和输出项,且它们不产生副作用时才?#34892;А?#25105;们可以理解为它们是“纯函数”才行。这个“可被计算”的模型有一个好处,它很容易通过并行和缓存的方法,就减少计算量。Bazel就是这样的,它会对独立的构建任务缓存产生的输出结果,即使在云端的时候!

            为什么要强调云端的缓存问题呢?如果Bazel能够构建后?#19968;?#23384;在云端,任何人都能利用这个构建结果。如果你是一个大公司肯定需要这样,即使小团队也能受益于它。Bazel并不是绑定于某个云平台的,这就是?#30340;?#21487;以在Google Cloud, Azure, AWS, 或你自己的设备上获取缓存远程构建这个好处。

            好吧,虚的讲了很多了,让我们看个例子吧!

            noonoo
            noonoo
            翻译于 01/23 17:50
            0

            用Bazel构建TypeScript

            这个例子时在,我们构建一个小的ts项目,最终生成一个es5的js文件。 这个项目只有以?#24405;?#20010;模块:

            • Lexer -  输入字符串后,返回一个token数组

            • Parser - 输入一个token数组。返回抽像语法树AST.

            • Interpreter - accepts an AST and evaluates it

            • Application - wires everything together - passes the program to the lexer, feeds the parser with the lexer’s output, and the interpreter with the produced AST

            noonoo
            noonoo
            翻译于 01/23 18:04
            0

            配置Workspace环境

            我们的项目依赖npm包TypeScript, Bazel, 还有一个Bazel的TypeScript规则。 这?#25512;?#23427;项目没什么不同的。所以我们现在深入WORKSPACE 这个配置文件一探究竟:

            workspace(name = 'lang')
            
            http_archive(
                name = "build_bazel_rules_typescript",
                url = "https://github.com/bazelbuild/rules_typescript/archive/0.21.0.zip",
                strip_prefix = "rules_typescript-0.21.0",
            )
            
            # Fetch our Bazel dependencies that aren't distributed on npm
            load("@build_bazel_rules_typescript//:package.bzl", "rules_typescript_dependencies")
            rules_typescript_dependencies()
            
            # Setup TypeScript toolchain
            load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
            ts_setup_workspace()
            
            # Setup the Node.js toolchain
            load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories", "yarn_install")
            node_repositories()
            
            # Setup Bazel managed npm dependencies with the `yarn_install` rule.
            yarn_install(
              name = "npm",
              package_json = "http://:package.json",
              yarn_lock = "http://:yarn.lock",
            )

            要知道这篇文章只是一个浅显的入门介绍。事实上,你可能从未自己管理过Bazel 配置.

            上面这个文件使用的语言叫 Starlark,你可以认为它是Python语言的子集,这是我们声明的:

            1. workspace 名称是 lang

            2. 项目使用 Bazel’s TypeScript rules.要记住它和我们声明在package.json 的版本号是一致的。

            3. 下一步,我们获取Bazel’s的依赖项 build_bazel_rules_typescript

            4. 设置 TypeScript workspace

            5. 设置 Bazel’s Node.js 的构建工具链. 它是由 Bazel team 维护的一组工具,所以我们可以在此使用 Node.js

            6. 最后我们声明一个规则让Bazel 管理 npm 依赖!

            如果上面代码看不明白也没关系,只要记住  load 差不多是Node.js中的 require, 不同的是load 还可?#28304;?#32593;络地址获取依赖!

             

            noonoo
            noonoo
            翻译于 01/23 19:47
            0

            配置编译目标

            我们深入到更细的粒度上。我?#21069;?#39033;目中独立的模块当成一个个 Bazel 包,在这每一个包中,我们定义一个编译目标。我们上面提到过,我?#21069;?#27599;个包看作一个文件夹,它包含里面的文件以及一个构建规则。

            每个文件夹都有一个BUILD 或 BUILD.bzl 文件。先看一下要项目中的BUILD文件:

            package(default_visibility = ["http://visibility:public"])
            
            load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
            
            ts_library(
              name = "app",
              srcs = ["test.ts"],
              deps = ["http://lexer", "http://parser", "http://interpreter"],
            )
            
            load("@build_bazel_rules_nodejs//:defs.bzl", "rollup_bundle")
            
            rollup_bundle(
              name = "bundle",
              entry_point = "test.js",
              deps = [":app"],
            )

            我们首先定义这个包是否对外可见,之后加载2个Bazel的规则:

            • ts_library - 用它来编译Typescript文件

            • rollup_bundle - 调用 Rollup.js 把各模块打包到一个文件里去。

             ts_library 规则用来构建名为 app 的目标. 这个app的构建目标就是把各个模块串联到一起后的结果. 它依赖于 lexerparser, and the interpreter. 在这三个文件夹中,还都有着各自的 BUILD 文件,内容差不多也是上面样子.  比如 parser的内容:

            package(default_visibility = ["http://visibility:public"])
            
            load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
            
            ts_library(
                name = "parser",
                srcs = glob(["*.ts"]),
                deps = ["http://lexer"],
            )

            这里我们用glob 来限定源文件,另外这个模块还依赖着 lexer  模块

            诸多依赖就有诸多构建目标,这可能带来混乱。Bazel 有个简洁的功能是依赖关系图必须是静态可分析的。我们能用Bazel查询语法,直?#30828;?#35810;依赖关系图。来让我看看看它什么样子吧!

            第一步,用  yarn 来安装  package.json 中的所有依赖包,这样就自动安装好 Bazel 。

            yarn

            启动bazel (可能要先安装graphviz才行)

            ./node_modules/.bin/bazel query --output=graph ... | dot -Tpng > graph.png

            上面命令的输出结果如下:

            我们看到各个目标间的依赖关系。

             

            noonoo
            noonoo
            翻译于 01/24 10:11
            0

            现在我们可以构建整个项目:

            ./node_modules/.bin/bazel build :bundle

            可以预料上面命令需要一点点时间,因为Bazel加载workspace中的依赖。 之后每一步就应该是瞬间完成了。

            现在来验证一下,执行构建后的bundle是否符合预期:

            node bazel-bin/bundle.js
            43

            当你构建过一次Bazel目标后,工作空间会产生许多symlinks,它?#21069;?#21547;诸多构建产物。如果你不想要,你可以通过bazel.rc来配置

             

             

             

             

            noonoo
            noonoo
            翻译于 01/24 10:21
            0

            监听模式

            怎么监听项目文件的变化,及时进行rebuilding呢?为了这个目的,我们要安装运行 @bazel/ibazel  包

            # Don’t forget yarn add -D @bazel/ibazel
            ./node_modules/.bin/ibazel build :app

            通过ibazel and bazel 包,在依赖直接或间接变化时,它会重新构建目标

            注意,在上面命令中,我们构建的是 :app 的目标。这是因为在代码开发中,基于Bazel的Rollup.js规则,我们不可能直接编码影响到 :bundle 这个构建目标。(言外之意是, :bundle 完全是通过   :app  生成的)

            现在让我们创建npm的命令缩写来代替 ./node_modules/.bin/bazel or ./node_modules/.bin/ibazel

            package.json 添加下面两句话:

            {
              "name": "bazel-demo",
              "license": "MIT",
              "scripts": {
                "build": "bazel build :bundle",
                "watch": "ibazel build :app"
              },
              "devDependencies": {
                "@bazel/bazel": "^0.19.1",
                "@bazel/typescript": "0.21.0",
                "typescript": "^3.1.6"
              }
            }

            现在运行yarn build 来重新构建项目或 yarn watch  来监听并自动构建项目。

            noonoo
            noonoo
            翻译于 01/24 10:32
            0

            结束语

            本篇中,我们关注谷歌的构建系统 Bazel。文章解释了 Bazel 解决了哪些问题,来提供给我们一个快速灵活的构建解决方案。

            在本篇的第二部分,我们通过一个小型的 Typescript 项目演示了构建的例?#21360;?#25105;们编译一组文件然后用 Rollup.js 打包输出为一个文件。在例子里,我们解释了什么是工作空间、构建目标、包,以及对它们进行配置。

            ?#38142;耍?#25105;们能看到 Bazel 的核心能力:静态的依赖关系图,它允许了像缓存、并行等的的简洁优化。在下篇文章中,我们将更近的关注一下?#38405;?#30340;实现!

            noonoo
            noonoo
            翻译于 01/24 10:48
            1
            本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链?#21360;?/div>
            我们的翻译工作遵照 CC 协议,如果我们的工作有?#22336;?#21040;您的权益,请及时联系我们。
            加载中

            评论(1)

            noonoo
            noonoo
            文中有?#34892;?#38169;?#21482;?#28431;掉字, 但翻译结果不让修?#27169;??
            返回顶部
            顶部
            广东快乐十分实时开奖

                  <output id="ilehw"><bdo id="ilehw"><nobr id="ilehw"></nobr></bdo></output>
                  <dl id="ilehw"><font id="ilehw"></font></dl>

                            <output id="ilehw"><bdo id="ilehw"><nobr id="ilehw"></nobr></bdo></output>
                            <dl id="ilehw"><font id="ilehw"></font></dl>
                              1. 黑龙江快乐十分走势图50 快乐8彩票官网 网上买山西11选5 老快3福彩走势图带连线 广东快乐十分前三直遗漏 广东时时彩开奖现场 体彩云南时时彩开奖结果查询 白小姐一肖一码欺欺准待 陕西快乐十分投注技巧 香港六合彩官网 黑龙江快乐扑克派秒杀 七乐彩走势图带连线图 昨天晚上双色球号码 扬红公式规律集合 四川时时彩qq群