<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: JiaLiPassion</title>
    <description>The latest articles on DEV Community by JiaLiPassion (@jialipassion).</description>
    <link>https://dev.to/jialipassion</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F51343%2F4936e5b0-a673-4a78-a821-c49061ab7028.jpeg</url>
      <title>DEV Community: JiaLiPassion</title>
      <link>https://dev.to/jialipassion</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jialipassion"/>
    <language>en</language>
    <item>
      <title>Build Typescript Project with Bazel Chapter 2: File Structure</title>
      <dc:creator>JiaLiPassion</dc:creator>
      <pubDate>Mon, 30 Mar 2020 18:57:51 +0000</pubDate>
      <link>https://dev.to/thisdotmedia/build-typescript-project-with-bazel-chapter-2-file-structure-254o</link>
      <guid>https://dev.to/thisdotmedia/build-typescript-project-with-bazel-chapter-2-file-structure-254o</guid>
      <description>&lt;h2&gt;
  
  
  Build Typescript Project with Bazel Chapter 2: File Structure
&lt;/h2&gt;

&lt;p&gt;In the last &lt;a href="https://dev.to/thisdotmedia/build-typescript-project-with-bazel-chapter-1-bazel-introduction-1c9o"&gt;chapter&lt;/a&gt;, we introduced the basic concept of Bazel. In this blog, I would like to talk about the file structure of Bazel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concept and Terminology
&lt;/h3&gt;

&lt;p&gt;Before we introduce the file structure, we need to understand several key concepts and terminology in Bazel.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Workspace&lt;/li&gt;
&lt;li&gt;Package&lt;/li&gt;
&lt;li&gt;Target&lt;/li&gt;
&lt;li&gt;Rule&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These concepts, and terminology, are composed to &lt;code&gt;Build File&lt;/code&gt;, which Bazel will analyze, and execute.&lt;/p&gt;

&lt;p&gt;The basic relationship among these concepts looks like this &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EcuuCktk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://images.ctfassets.net/zojzzdop0fzx/1L9P8a6KOMNR1TqRzYJcrl/5b75094c9fe648b72094d31c7e9ad6ea/Screenshot_from_2020-03-15_22-45-19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EcuuCktk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://images.ctfassets.net/zojzzdop0fzx/1L9P8a6KOMNR1TqRzYJcrl/5b75094c9fe648b72094d31c7e9ad6ea/Screenshot_from_2020-03-15_22-45-19.png" alt="graph"&gt;&lt;/a&gt;, we will discuss the details one by one.&lt;/p&gt;

&lt;h4&gt;
  
  
  Workspace
&lt;/h4&gt;

&lt;p&gt;A "workspace" refers to the directories, which contain&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The source files of the project.&lt;/li&gt;
&lt;li&gt;Symbolic links contain the build output.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And the Bazel definition is in a file named &lt;code&gt;WORKSPACE&lt;/code&gt;, or &lt;code&gt;WORKSPACE.bazel&lt;/code&gt; at the root of the project directory. NOTE, one project can only have one &lt;code&gt;WORKSPACE&lt;/code&gt; definition file.&lt;/p&gt;

&lt;p&gt;Here is an example of the &lt;code&gt;WORKSPACE&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;workspace(
    name = "com_thisdot_bazel_demo",
)

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

# Fetch rules_nodejs so we can install our npm dependencies
http_archive(
    name = "build_bazel_rules_nodejs",
    sha256 = "ad4be2c6f40f5af70c7edf294955f9d9a0222c8e2756109731b25f79ea2ccea0",
    urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.38.3/rules_nodejs-0.38.3.tar.gz"],
)

load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories", "yarn_install")

node_repositories()

yarn_install(
    name = "npm",
    package_json = "//:package.json",
    yarn_lock = "//:yarn.lock",
)

# Install all Bazel dependencies of the @npm npm packages
load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")

install_bazel_dependencies()

# Setup the rules_typescript toolchain
load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace")

ts_setup_workspace()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In a &lt;code&gt;WORKSPACE&lt;/code&gt; file, we should&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define the name of the workspace. The name should be unique globally, or at least unique in your organization. You could use the reverse dns name, such as &lt;code&gt;com_thisdot_bazel_demo&lt;/code&gt;, or the name of the project on GitHub.&lt;/li&gt;
&lt;li&gt;Install environment related packages, such as &lt;code&gt;yarn/npm/bazel&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Setup toolchains needed to &lt;code&gt;build/test&lt;/code&gt; the project, such as &lt;code&gt;typescript/karma&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once &lt;code&gt;WORKSPACE&lt;/code&gt; is ready, application developers don't really need to touch this file.&lt;/p&gt;

&lt;h4&gt;
  
  
  Package
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;The primary unit of code organization (something like module) in a repository&lt;/li&gt;
&lt;li&gt;Collection of related files and a specification of the dependencies among them&lt;/li&gt;
&lt;li&gt;Directory containing a file named BUILD or BUILD.bazel, residing beneath the top-level directory in the workspace&lt;/li&gt;
&lt;li&gt;A package includes all files in its directory, plus all subdirectories beneath it, except those which, themselves, contain a BUILD file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is important to know how to split a project into &lt;code&gt;package&lt;/code&gt;. It should be easy for the users to develop/test/share the unit of a &lt;code&gt;package&lt;/code&gt;. If the unit is too big, the &lt;code&gt;package&lt;/code&gt; has to be rebuilt on every package file change. If the unit is too small, it will be very hard to maintain and share. So, this is not an issue of &lt;code&gt;Bazel&lt;/code&gt;. It is a general problem of project management.&lt;/p&gt;

&lt;p&gt;In Bazel, every &lt;code&gt;package&lt;/code&gt; will have a &lt;code&gt;BUILD.bazel&lt;/code&gt; file, containing all of the &lt;code&gt;build&lt;/code&gt;/&lt;code&gt;test&lt;/code&gt;/&lt;code&gt;bundle&lt;/code&gt; target definitions.&lt;/p&gt;

&lt;p&gt;For example, here is a &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2wDEQzqd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://images.ctfassets.net/zojzzdop0fzx/5IBxi47Pttab99Mqi1Srlk/92330b615770fa77b835ce251a4ae476/Screenshot_from_2020-03-15_22-48-05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2wDEQzqd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://images.ctfassets.net/zojzzdop0fzx/5IBxi47Pttab99Mqi1Srlk/92330b615770fa77b835ce251a4ae476/Screenshot_from_2020-03-15_22-48-05.png" alt="screenshot"&gt;&lt;/a&gt; of the &lt;a href="https://github.com/angular/angular"&gt;Angular&lt;/a&gt; structure. Every directory under packages directory is a &lt;code&gt;package&lt;/code&gt; of code organization, and also the build organization of Bazel.&lt;/p&gt;

&lt;p&gt;Let's take a look at the file structure of &lt;code&gt;gulpjs&lt;/code&gt; in &lt;a href="https://github.com/angular/angular"&gt;Angular&lt;/a&gt;, so we can have a better understanding about the difference between Bazel and gulpjs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gulp.task('build-animations', () =&amp;gt; {});;
gulp.task('build-core', () =&amp;gt; {});
gulp.task('build-core-schematics', () =&amp;gt; {});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In most cases,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a gulpjs file doesn't have 1:1 relationship to the package directory.&lt;/li&gt;
&lt;li&gt;a gulpjs file can reference any files inside the project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But for Bazel,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each &lt;code&gt;package&lt;/code&gt; should have their own &lt;code&gt;BUILD.bazel&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;BUILD.bazel&lt;/code&gt; can only reference the file inside the current &lt;code&gt;package&lt;/code&gt;, and if the current package depends on other packages, we need to reference the Bazel build &lt;code&gt;target&lt;/code&gt; from the other packages instead of the files directly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a Bazel Package directory structure in &lt;a href="https://github.com/angular/angular/issues"&gt;Angular&lt;/a&gt; repo. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jCnDS8XR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://images.ctfassets.net/zojzzdop0fzx/2ukLvwyybLz9cdjbuMIeb/fa9c71afcb44da025df5269c66bd4088/Screenshot_from_2020-03-15_22-51-24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jCnDS8XR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://images.ctfassets.net/zojzzdop0fzx/2ukLvwyybLz9cdjbuMIeb/fa9c71afcb44da025df5269c66bd4088/Screenshot_from_2020-03-15_22-51-24.png" alt="Angular"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Build File
&lt;/h4&gt;

&lt;p&gt;Before we talk about &lt;code&gt;target&lt;/code&gt;, let's take a look at the content of a &lt;code&gt;BUILD.bazel&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package(default_visibility = ["//visibility:private"])

load("@npm_bazel_typescript//:index.bzl", "ts_library")

ts_library(
    name = "lib",
    srcs = [":lib.ts"],
    visibility = ["//visibility:public"],
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The language of the &lt;code&gt;BUILD.bazel&lt;/code&gt; file is &lt;code&gt;Starlark&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Starlark&lt;/code&gt; is a subset of &lt;code&gt;Python&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It is a very feature-limited language. A ton of &lt;code&gt;Python&lt;/code&gt; features, such as &lt;code&gt;class&lt;/code&gt;, &lt;code&gt;import&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;, &lt;code&gt;yield&lt;/code&gt;, &lt;code&gt;lambda&lt;/code&gt;, &lt;code&gt;is&lt;/code&gt;, &lt;code&gt;raise&lt;/code&gt;, are not supported.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Recursion&lt;/code&gt; is not allowed.&lt;/li&gt;
&lt;li&gt;Most of Python's builtin methods are not supported.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So &lt;code&gt;Starlark&lt;/code&gt; is a very very simple language, and only supports very limited &lt;code&gt;Python&lt;/code&gt; syntax.&lt;/p&gt;

&lt;h4&gt;
  
  
  Target
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;BUILD.bazel&lt;/code&gt; file contains build targets. Those &lt;code&gt;target&lt;/code&gt;s are the definitions of the &lt;code&gt;build&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;, and &lt;code&gt;bundle&lt;/code&gt; work we want to achieve.&lt;/p&gt;

&lt;p&gt;The build target can represent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files&lt;/li&gt;
&lt;li&gt;Rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The target can also depend on other targets&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Circular dependencies are not allowed&lt;/li&gt;
&lt;li&gt;Two targets, generating the same output, will cause a problem&lt;/li&gt;
&lt;li&gt;Target dependency must be declared explicitly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see the previous sample,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package(default_visibility = ["//visibility:private"])

load("@npm_bazel_typescript//:index.bzl", "ts_library")

ts_library(
    name = "lib",
    srcs = [":lib.ts"],
    visibility = ["//visibility:public"],
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;ts_library&lt;/code&gt; is a rule imported from &lt;code&gt;@npm_bazel_typescript&lt;/code&gt; workspace, and &lt;code&gt;ts_library(name = "lib")&lt;/code&gt; is a &lt;code&gt;target&lt;/code&gt;. The name is &lt;code&gt;lib&lt;/code&gt;, and this target defines the metadata for compiling the &lt;code&gt;lib.ts&lt;/code&gt; with &lt;code&gt;ts_library&lt;/code&gt; rule.&lt;/p&gt;

&lt;h5&gt;
  
  
  Label
&lt;/h5&gt;

&lt;p&gt;Every target has a unique name called &lt;code&gt;label&lt;/code&gt;. For example, if the &lt;code&gt;BUILD.bazel&lt;/code&gt; file above is under &lt;code&gt;/lib&lt;/code&gt; directory, then the label of the target is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@com_thisdot_bazel_demo//lib:lib
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The label is composed of several parts.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the name of the workspace: &lt;code&gt;@com_thisdot_bazel_demo&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;the name of the package: &lt;code&gt;lib&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;the name of the target: &lt;code&gt;lib&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, the composition is &lt;code&gt;&amp;lt;workspace name&amp;gt;//&amp;lt;package name&amp;gt;:&amp;lt;target name&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Most of the times, the name of the workspace can be omitted, so the label above can also be expressed as &lt;code&gt;//lib:lib&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, if the name of the target is the same as the package's name, the name of the target can also be omitted. Therefore, the label above can also be expressed as &lt;code&gt;//lib&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;NOTE: The label for the target needs to be unique in the workspace.&lt;/p&gt;

&lt;h4&gt;
  
  
  Visibility
&lt;/h4&gt;

&lt;p&gt;We can also define the visibility to define whether the rule inside this package can be used by other packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package(default_visibility = ["//visibility:private"])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The visibility can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;private&lt;/code&gt;: the rules can be only used inside the current package.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;public&lt;/code&gt;: the rules can be used everywhere.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;//some_package:package_scope&lt;/code&gt;: the rules can only be used in the specified scope under &lt;code&gt;//some_package&lt;/code&gt;. The &lt;code&gt;package_scope&lt;/code&gt; can be: &lt;code&gt;__pkg__&lt;/code&gt;/&lt;code&gt;__subpackages__&lt;/code&gt;/&lt;code&gt;package group&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if the rules in one package can be accessed from the other package, we can use &lt;code&gt;load&lt;/code&gt; to import them. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;load("@npm_bazel_typescript//:index.bzl", "ts_library")
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here, we import the &lt;code&gt;ts_library&lt;/code&gt; rule from the Bazel typescript package.&lt;/p&gt;

&lt;h4&gt;
  
  
  Target
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Target can be &lt;code&gt;Files&lt;/code&gt; or &lt;code&gt;Rule&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Target has &lt;code&gt;input&lt;/code&gt; and &lt;code&gt;output&lt;/code&gt;. The &lt;code&gt;input&lt;/code&gt; and &lt;code&gt;output&lt;/code&gt; are known at build time.&lt;/li&gt;
&lt;li&gt;Target will only be rebuilt when &lt;code&gt;input&lt;/code&gt; changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take a look at &lt;code&gt;Rule&lt;/code&gt; first.&lt;/p&gt;

&lt;h5&gt;
  
  
  Rule
&lt;/h5&gt;

&lt;p&gt;The rule is just like a &lt;code&gt;function&lt;/code&gt; or &lt;code&gt;macro&lt;/code&gt;. It can accept &lt;code&gt;named parameters&lt;/code&gt; as options. Just like in the previous post, calling a rule will not execute an action. It is just metadata. Bazel will decide what to do.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ts_library(
    name = "lib",
    srcs = [":lib.ts"],
    visibility = ["//visibility:public"],
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So here, we use the &lt;code&gt;ts_library&lt;/code&gt; rule to define a target, and the name is &lt;code&gt;lib&lt;/code&gt;. The srcs is &lt;code&gt;lib.ts&lt;/code&gt; in the same directory. The visibility is &lt;code&gt;public&lt;/code&gt;, so this target can be accessed from the other packages.&lt;/p&gt;

&lt;h5&gt;
  
  
  Rule Naming
&lt;/h5&gt;

&lt;p&gt;It is very important to follow the naming convention when you want to create your own rule.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;*_binary&lt;/code&gt;: executable programs in a given language (nodejs_binary)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;*_test&lt;/code&gt;: special _binary rule for testing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;*_library&lt;/code&gt;: compiled module for a given language (ts_library)&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Rule common attributes
&lt;/h5&gt;

&lt;p&gt;Several common attributes exist in almost all rules.For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ts_library(
    name = "lib",
    srcs = [":index.ts"],
    tags = ["build-target"],
    visibility = ["//visibility:public"],
    deps = [
        ":date",
        ":user",
    ],
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;name: unique name within this package&lt;/li&gt;
&lt;li&gt;srcs: inputs of the target, typically files&lt;/li&gt;
&lt;li&gt;deps: compile-time dependencies&lt;/li&gt;
&lt;li&gt;data: runtime dependencies&lt;/li&gt;
&lt;li&gt;testonly: target which should be executed only when running Bazel test&lt;/li&gt;
&lt;li&gt;visibility: specifies who can make a dependency on the given target&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see another example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http_server(
   name = "prodserver",
   data = [
       "index.html",
       ":bundle",
       "styles.css",
   ],
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here, we use the &lt;code&gt;data&lt;/code&gt; attribute. The &lt;code&gt;data&lt;/code&gt; will only be used at runtime.It will not be analyzed by Bazel at build time.&lt;/p&gt;

&lt;p&gt;So, in this blog, we introduced the basic Bazel structure concepts. In the next blog, we will introduce how to query Bazel targets.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This Dot Labs is a modern web consultancy focused on helping companies realize their digital transformation efforts. For expert architectural guidance, training, or consulting in React, Angular, Vue, Web Components, GraphQL, Node, Bazel, or Polymer, visit [thisdotlabs.com]((&lt;a href="https://www.thisdotlabs.com"&gt;https://www.thisdotlabs.com&lt;/a&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This Dot Media is focused on creating an inclusive and educational web for all. We keep you up to date with advancements in the modern web through events, podcasts, and free content. To learn, visit &lt;a href="https://www.thisdot.co"&gt;thisdot.co&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bazel</category>
    </item>
    <item>
      <title>Event Coalescing to improve performance</title>
      <dc:creator>JiaLiPassion</dc:creator>
      <pubDate>Thu, 16 Jan 2020 01:18:04 +0000</pubDate>
      <link>https://dev.to/angular-jp/event-coalescing-to-improve-performance-1ca6</link>
      <guid>https://dev.to/angular-jp/event-coalescing-to-improve-performance-1ca6</guid>
      <description>&lt;h1&gt;
  
  
  Event Bubbling の性能の問題
&lt;/h1&gt;

&lt;p&gt;下記のAngularアプリケーションでのHTMLテンプレートコードを見ましょう。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"doSomething()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"doAnotherThing()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Button&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture"&gt;Event Bubbling&lt;/a&gt; のため、DivのなかのButtonをクリックしたら、両方のEvent ListenerがTriggerされます。この２つのEvent Listenerが全部Change Detectionを実行します。実際はこのようなケースでChange Detectionを一回だけ実行したいです。特にこのようなケースがAngular MaterialとかUI ライブラリで結構普通のケースですので、性能改善したいです。&lt;/p&gt;

&lt;h1&gt;
  
  
  実行順番
&lt;/h1&gt;

&lt;p&gt;まず上記のケースでEvent ListenerとChange Detectionの実行順番を見ましょう。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// event listener for parent div&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;event listener for parent div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;doAnotherThing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// event listener for inner button&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;event listener for inner button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;そして、Zone.jsがEvent ListenerをMonkey patchされましたので、下記のような感じのコードになりました。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;eventHandler&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;realHandler&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt; &lt;span class="c1"&gt;// doSomething あるいはdoAnotherThingのDelegate&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;applicationRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;そしたら、Buttonをクリックするとき、実行の順番が下記のようになりました。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event listener for inner button
applicationRef.tick
event listener for parent div
applicationRef.tick
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;実際ほしいのは&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event listener for inner button
event listener for parent div
applicationRef.tick
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;です。&lt;/p&gt;

&lt;h2&gt;
  
  
  解決方法
&lt;/h2&gt;

&lt;p&gt;Change Detectionを同期ではなく、非同期で実行することです。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;isChangeDetectionScheduled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;eventHandler&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;realHandler&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt; &lt;span class="c1"&gt;// doSomething あるいはdoAnotherThingのDelegate&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isChangeDetectionScheduled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;isChangeDetectionScheduled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;isChangeDetectionScheduled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;applicationRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;のような感じのコードでChange DetectionをrequestAnimationFrameのSchedulerで実行させ、そしてもしScheduleされたTaskがあったら、スキップして、なかったら、Scheduleするということです。&lt;/p&gt;

&lt;h2&gt;
  
  
  設定方法
&lt;/h2&gt;

&lt;p&gt;bootstrapModuleのとき、かきのOptionを設定することができます。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;platformBrowserDynamic&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;bootstrapModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;ngZoneEventCoalescing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  副作用
&lt;/h2&gt;

&lt;p&gt;このオプションをTrueにしたら、もともと同期のChange Detectionが非同期になりました、普通のアプリケーションには影響がないですが、Google 内部でのEdge Caseで同期のChange Detectionが求めるテストケースがあるらしくて、それ以外が特に既存のアプリケーションには影響ないはずです。&lt;br&gt;
この機能がすでに最新バージョンで使えますので、なにか問題が発見されたら、ぜひAngular RepoにIssueを提出ください。&lt;/p&gt;

&lt;p&gt;以上です。&lt;/p&gt;

&lt;p&gt;どうもありがとうございました！&lt;/p&gt;

</description>
      <category>zonejs</category>
      <category>angular</category>
      <category>eventlistener</category>
      <category>performance</category>
    </item>
    <item>
      <title>Build Typescript Project with Bazel Chapter 1: Bazel introduction</title>
      <dc:creator>JiaLiPassion</dc:creator>
      <pubDate>Wed, 08 Jan 2020 15:47:55 +0000</pubDate>
      <link>https://dev.to/thisdotmedia/build-typescript-project-with-bazel-chapter-1-bazel-introduction-1c9o</link>
      <guid>https://dev.to/thisdotmedia/build-typescript-project-with-bazel-chapter-1-bazel-introduction-1c9o</guid>
      <description>&lt;p&gt;Bazel is a fast, scalable, incremental, and universal (for any languages/frameworks) build tool, and is especially useful for big mono repo projects.&lt;/p&gt;

&lt;p&gt;I would like to write a series of blogs to introduce the concept of how to build a typescript project with Bazel.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chapter 1: Bazel Introduction&lt;/li&gt;
&lt;li&gt;Chapter 2: Bazel file structure and Bazel Query&lt;/li&gt;
&lt;li&gt;Chapter 3: Build/Develop/Test a typescript project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In chapter 1, I would like introduce basic Bazel concepts, and define some of the benefits we can expect from using Bazel.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is Bazel?&lt;/li&gt;
&lt;li&gt;Bazel: Correctness&lt;/li&gt;
&lt;li&gt;Bazel: Fast&lt;/li&gt;
&lt;li&gt;Bazel: Universal&lt;/li&gt;
&lt;li&gt;Bazel: Industrial grade&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is Bazel?
&lt;/h2&gt;

&lt;p&gt;As you may know, we already have a lot of build tools. They include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CI tools: Jenkins/CircleCI&lt;/li&gt;
&lt;li&gt;Compile tools: tsc/sass&lt;/li&gt;
&lt;li&gt;Bundle tools: webpack/rollup&lt;/li&gt;
&lt;li&gt;Coordinate tools: make/grunt/gulp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So what is Bazel? Does it simply replace Jenkins or Webpack?&lt;br&gt;
@AlexEagle helped us answer this question at &lt;a href="https://www.youtube.com/watch?v=J1lnp-nU4wM"&gt;ngconf 2019&lt;/a&gt;, but here is a great picture that will explain a little as well.&lt;br&gt;
&lt;a href="//images.ctfassets.net/r8ivd0qscuik/10OVEYdNKDHIOi03MaQKa3/fee6964173547c7535f58fd7bec8663f/Screen_Shot_2019-11-19_at_11.29.45.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/r8ivd0qscuik/10OVEYdNKDHIOi03MaQKa3/fee6964173547c7535f58fd7bec8663f/Screen_Shot_2019-11-19_at_11.29.45.png" alt="Build tools"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So Bazel is a build tool, used to coordinate other tools (compile/bundle tools), and will use all the existing tools (such as tsc/webpack/rollup) to do the underlying work.&lt;/p&gt;

&lt;p&gt;Another graph, also from @AlexEagle, will show this relationship more clearly.&lt;br&gt;
&lt;a href="//images.ctfassets.net/r8ivd0qscuik/4KuZZmo3y1VAmePKL1WbIj/83145449fac86107776a160fea967137/Screen_Shot_2019-11-19_at_11.43.34.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/r8ivd0qscuik/4KuZZmo3y1VAmePKL1WbIj/83145449fac86107776a160fea967137/Screen_Shot_2019-11-19_at_11.43.34.png" alt="Bazel is a Hub"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok, so Bazel is at the same position as Gulp, why not continue to use Gulp?&lt;/p&gt;

&lt;p&gt;To answer this question, let's think about what the goal of the build tool is.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Essential:

&lt;ul&gt;
&lt;li&gt;Correct - don't need to worry about environmental pollution.&lt;/li&gt;
&lt;li&gt;Fast

&lt;ul&gt;
&lt;li&gt;Incremental&lt;/li&gt;
&lt;li&gt;Parallelism&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Predictable - Same input will guarantee the same output.&lt;/li&gt;
&lt;li&gt;Reusable - Build logic can be easily composed and reused.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Nice to have:

&lt;ul&gt;
&lt;li&gt;Universal - support multiple languages and frameworks.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Correctness
&lt;/h2&gt;

&lt;p&gt;This is the most important requirement. We all want our build systems to be stable, and we don't want them to generate unexpected results. Therefore, we want every build to be executed in an isolated environment. Otherwise, we will run into problems if, for example, we forget to delete some temp files, forget to reset environment variables, or if the build only works under certain conditions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Sandboxing: Bazel supports sandboxing to isolate the environment. When we do a Bazel build, it will create an isolated working folder, and Bazel will run the build process under this folder.  This is what we would call "sandboxing". Bazel will then restrict the access to the files outside of this folder. Also, Bazel makes sure that elements of the build tool, such as the compiler, only know their own input files, so the output will only depend on input. &lt;br&gt;
&lt;a href="//images.ctfassets.net/r8ivd0qscuik/1UvOCTstu96n8RID4rAQVE/0178676af60b5e6bd045416e7edd960b/xy087mf2gsrbfdbe3t4r.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/r8ivd0qscuik/1UvOCTstu96n8RID4rAQVE/0178676af60b5e6bd045416e7edd960b/xy087mf2gsrbfdbe3t4r.png" alt="xy087mf2gsrbfdbe3t4r"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The rule can only access an input file. Unlike a Gulp task, a Bazel rule can only access the files declared as input (we will talk about the target/rule in detail later).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is an example of a Gulp task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gulp.task('compile', ['depTask'], () =&amp;gt; {
  // do compile
  gulp.src(["a.ts"])
      .pipe(tsc(...));
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So inside of a Gulp task, there is just a normal function. There is no concept of &lt;code&gt;Input&lt;/code&gt;, and &lt;code&gt;dependencies&lt;/code&gt; only tells gulp to run tasks in a specified order, so the task can access any files, and use any environmental variables with no restrictions. Gulp will have no idea which files are used in this task, so if some logic depends on the unintended file access/environment reference, it is impossible for Gulp to guarantee that the task will always generate the same results.&lt;/p&gt;

&lt;p&gt;Let's see a Bazel target.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ts_library(
    name = "compile",
    srcs = ["a.ts"],
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We will talk about the Bazel target/rule in more detail in the next chapter. Here, we will declare a Bazel target with a ts_library rule. Unlike with a Gulp task, here we have a strict input which is &lt;code&gt;srcs = ["a.ts"]&lt;/code&gt;, so when Bazel decides to execute this target, the &lt;code&gt;typescript compiler&lt;/code&gt; can only access the file &lt;code&gt;a.ts&lt;/code&gt; inside of the sandbox, and nowhere else. Therefore, there is no way that the Bazel target will produce &lt;code&gt;wrong&lt;/code&gt; results because of the unpredictable environment or input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fast
&lt;/h2&gt;

&lt;p&gt;Bazel is incremental because Bazel is &lt;code&gt;declarative&lt;/code&gt; and &lt;code&gt;predictable&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bazel is Declarative
&lt;/h3&gt;

&lt;p&gt;Let's use Gulp to compile those two files, in order to demonstrate that Gulp is &lt;code&gt;imperative&lt;/code&gt; and Bazel is &lt;code&gt;declarative&lt;/code&gt;. Let's see an example with Gulp.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// gulpfile.js
gulp.task('compile', () =&amp;gt; {
  gulp.src(['user.ts', 'print.ts'])
      .pipe(tsc(...))
      .pipe(gulp.desc('./out'));
});

gulp.task('test', ['compile'], () =&amp;gt; {
   // run test depends on compile task
});

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When we run &lt;code&gt;gulp test&lt;/code&gt; for the first time, both the &lt;code&gt;compile&lt;/code&gt;, and the &lt;code&gt;test&lt;/code&gt; tasks will be executed. And then, even if we don't change any files, those two tasks will still be executed if we run &lt;code&gt;gulp test&lt;/code&gt; again. Gulp is &lt;code&gt;imperative&lt;/code&gt;, so we just have to tell it to do those two commands, and Gulp will do what we asked. Specifically, it checks the &lt;code&gt;dependency&lt;/code&gt;, and guarantees the execution order. That's all.&lt;/p&gt;

&lt;p&gt;Let's see how Bazel works. Here, we have two typescript files: &lt;code&gt;user.ts&lt;/code&gt;, and &lt;code&gt;print.ts&lt;/code&gt;. &lt;code&gt;print.ts&lt;/code&gt; uses &lt;code&gt;user.ts&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// user.ts
export class User {
  constructor(public name: string) {}

  toString() {
    return `user: ${this.name}`;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// print.ts
import {User} from './user';

function printUser(user: User) {
  console.log(`the user is ${user.name}`);
}

printUser(new User('testUser'));
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To demonstrate that Bazel is declarative, let's use two Bazel build targets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# src/BUILD.bazel
ts_library(
    name = "user",
    srcs = ["user.ts"],
)

ts_library(
    name = "print",
    srcs = ["print.ts"],
    deps = [":user"]
)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So we &lt;code&gt;declare&lt;/code&gt; two Bazel targets, &lt;code&gt;user&lt;/code&gt;, and &lt;code&gt;print&lt;/code&gt;. The &lt;code&gt;print&lt;/code&gt; target depends on the &lt;code&gt;user&lt;/code&gt; target. All those targets are using the &lt;code&gt;ts_library&lt;/code&gt; rule. It contains the metadata to tell Bazel how to compile the typescript files. And again, all this information is just a &lt;code&gt;definition&lt;/code&gt;. It's not about &lt;code&gt;commands&lt;/code&gt;, so when you use Bazel to build those targets, it is up to Bazel to decide whether to execute those rules or not.&lt;/p&gt;

&lt;p&gt;Let's see the result first.&lt;/p&gt;

&lt;p&gt;When we run &lt;code&gt;bazel build //src:print&lt;/code&gt;, both the &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;print&lt;/code&gt; targets will be compiled, which makes sense. When we run &lt;code&gt;bazel build //src:print&lt;/code&gt; again, you will find Bazel will not run any targets because nothing changed, and Bazel knows it. As a result, Bazel decides not to run any targets.&lt;/p&gt;

&lt;p&gt;Let's change something in &lt;code&gt;user.ts&lt;/code&gt;, and see what happens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// updated user.ts
export class User {
  constructor(public name: string) {}

  toString() {
    return `updated toString of user: ${this.name}`;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After we run &lt;code&gt;bazel build //src:print&lt;/code&gt; again, we may expect that both &lt;code&gt;user&lt;/code&gt; and &lt;code&gt;print&lt;/code&gt; will be compiled once more because &lt;code&gt;user.ts&lt;/code&gt; has been changed, and &lt;code&gt;print.ts&lt;/code&gt; references &lt;code&gt;user.ts&lt;/code&gt;, and the &lt;code&gt;print&lt;/code&gt; target depends on the &lt;code&gt;user&lt;/code&gt; target. But the result is that only the &lt;code&gt;user&lt;/code&gt; target has been compiled, and the &lt;code&gt;print&lt;/code&gt; target has not. Why? &lt;/p&gt;

&lt;p&gt;This is because changes in &lt;code&gt;user.ts&lt;/code&gt; don't impact &lt;code&gt;print.ts&lt;/code&gt;, and Bazel understands this.&lt;/p&gt;

&lt;p&gt;Let's check out the following graph, which describes the &lt;code&gt;input/output&lt;/code&gt; of the target.&lt;br&gt;
&lt;a href="//images.ctfassets.net/r8ivd0qscuik/5MUfDBZhp7ZUc15mxXjg09/e3b43b75f0ff32bad16a2a6aa5c2157a/5y0lhz43l0l7d6timlbe.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/r8ivd0qscuik/5MUfDBZhp7ZUc15mxXjg09/e3b43b75f0ff32bad16a2a6aa5c2157a/5y0lhz43l0l7d6timlbe.png" alt="Target input/output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So for &lt;code&gt;user&lt;/code&gt; target, the &lt;code&gt;input&lt;/code&gt; is &lt;code&gt;user.ts&lt;/code&gt;, and we have two outputs. One is &lt;code&gt;user.js&lt;/code&gt;, and the other is &lt;code&gt;user.d.ts&lt;/code&gt;.  The latter of the two is the typescript declaration file. So let's see the relationship between the &lt;code&gt;user&lt;/code&gt;, and &lt;code&gt;print&lt;/code&gt; target.&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/r8ivd0qscuik/1UvOCTstu96n8RID4rAQVE/0178676af60b5e6bd045416e7edd960b/xy087mf2gsrbfdbe3t4r.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/r8ivd0qscuik/1UvOCTstu96n8RID4rAQVE/0178676af60b5e6bd045416e7edd960b/xy087mf2gsrbfdbe3t4r.png" alt="Target dependency"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, we can see that the &lt;code&gt;print target&lt;/code&gt; depends on the &lt;code&gt;user target&lt;/code&gt;, and that it uses one of the user target's outputs, &lt;code&gt;user.d.ts&lt;/code&gt;, as it's own input. So, because we only updated &lt;code&gt;toString&lt;/code&gt; of &lt;code&gt;user.ts&lt;/code&gt;, and the &lt;code&gt;user.d.ts&lt;/code&gt; was not changed at all, Bazel analyses the &lt;code&gt;dependency graph&lt;/code&gt;.  As a result, it knows that only &lt;code&gt;user target&lt;/code&gt; needs to be built. Further, it also knows that the &lt;code&gt;print target&lt;/code&gt; doesn't need to be built because the inputs of the &lt;code&gt;print target&lt;/code&gt;, which are &lt;code&gt;user.d.ts&lt;/code&gt; and &lt;code&gt;print.ts&lt;/code&gt;, have not changed. Because of this, Bazel decides not to build &lt;code&gt;print target&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is very important to remember that Bazel is &lt;code&gt;declarative&lt;/code&gt; and not &lt;code&gt;imperative&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/r8ivd0qscuik/3j12azv1Sf1LwYcZGcWMav/5d7cb71f80c92cb80c8c0a7b353721b2/j6ioxcytjpoveua2g1xf.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/r8ivd0qscuik/3j12azv1Sf1LwYcZGcWMav/5d7cb71f80c92cb80c8c0a7b353721b2/j6ioxcytjpoveua2g1xf.png" alt="Dependency Graph"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bazel analyses the input/output of all build targets to determine which targets need to be executed.&lt;/p&gt;

&lt;p&gt;(We can generate the &lt;code&gt;dependency graph&lt;/code&gt; with &lt;code&gt;bazel query&lt;/code&gt;, and we will talk about it in the next chapter.)&lt;/p&gt;

&lt;p&gt;So Bazel can do &lt;code&gt;incremental&lt;/code&gt; builds based on the analysis of the &lt;code&gt;dependency graph&lt;/code&gt;, and only build the really impacted targets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bazel is Predictable (Bazel's Rules are Pure Functions)
&lt;/h3&gt;

&lt;p&gt;Also, all Bazel rules are &lt;code&gt;pure functions&lt;/code&gt;, so the same input will always result in the same output, hence Bazel is predictable. We can use the &lt;code&gt;input&lt;/code&gt; as a key to &lt;code&gt;cache&lt;/code&gt; the result of each target, and save the cache locally or remotely.&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/r8ivd0qscuik/2ifWFoxTtvJtEkCFZsbY4A/413f2c813d8747c893674add1c679069/cznutmv7vt7izys7pvub.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/r8ivd0qscuik/2ifWFoxTtvJtEkCFZsbY4A/413f2c813d8747c893674add1c679069/cznutmv7vt7izys7pvub.png" alt="Remote cache"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, developer 1 builds some targets, and pushes the result to &lt;code&gt;remote cache&lt;/code&gt;. The other developer can then directly use this cache without building those targets in their own environment.&lt;/p&gt;

&lt;p&gt;So these amazing features make Bazel super fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  Universal
&lt;/h2&gt;

&lt;p&gt;Bazel is a coordinate tool. It doesn't rely on any specified languages/frameworks, and it can build within almost all languages/frameworks from server to client, and from desktop to mobile.&lt;/p&gt;

&lt;p&gt;It is difficult and costly to employ a specialist team to handle builds with several build tools/frameworks when working on a full-stack project. In one of my previous projects, we used Maven to build a Java backend, used Webpack to build its frontend, and used XCode and Gradle to build iOS and Android clients. Consequently, we needed a special build team consisting of people that knew all of those build tools, which makes it very difficult to do an incremental build, cache the results, or share the build script with other projects.&lt;/p&gt;

&lt;p&gt;Bazel is also a perfect tool for mono repo, and full-stack projects that include multiple languages/frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Industrial Grade
&lt;/h2&gt;

&lt;p&gt;Bazel is not an experimental project. It is used in almost all projects inside Google. When I started contributing to Angular, I did not use Bazel.  Because of this, the time that Angular CI was taking was about 1 hour. Once Bazel was introduced to Angular CI, the time reduced to about 15 minutes, and the build process became much more stable, and less flaky than before, even with double the amount of test cases. It is amazing! I believe that Bazel will be the "must have" tool for many big projects.&lt;/p&gt;

&lt;p&gt;I really like Bazel, and in the next blog post, I would like to introduce Bazel's file structure with &lt;code&gt;bazel query&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Thanks for reading, and any feedback is appreciated.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enjoy this article? Head on over to &lt;a href="https://www.thisdotlabs.com"&gt;This Dot Labs&lt;/a&gt; and check us out!  We are a tech consultancy that does all things javascript and front end.  We specialize in open source software like, Angular, React and Vue.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
