각도+바젤: 준비됐어!

17800 단어 angularbazel
본고에서 저는 Bazel이 무엇인지, Angular CLI와 어떻게 결합하여 사용하는지, 그리고 왜 사용하는지 좋은 생각입니다.

바젤이 뭐예요?


Bazel은 구글이 개발한 다언어 기능을 갖춘 구축 도구/시스템이다.
이것은 확장할 수 있습니다. 이것은 다른 언어와 프레임워크에 대한 지원을 추가할 수 있음을 의미합니다.
코드의 특정 부분을 언제 재구성할지 알고 캐시 구축 부품을 캐시하여 속도가 매우 빠르다.

개념


작업공간: 작업공간은 생성할 원본 파일을 포함하는 루트 디렉터리입니다.그것은 적어도 WORKSPACE 라는 텍스트 파일이 있어야 한다.하위 디렉토리에 있는 파일WORKSPACE을 찾으면 상위 작업공간에서 해당 파일을 무시하여 새 작업공간을 만듭니다.
패키지: 작업공간과 유사합니다. 패키지는 BUILD (또는 BUILD.bazel) 파일에 의해 정의된 작업공간 아래의 디렉터리입니다.Package의 하위 디렉토리에 BUILD 파일이 있는 경우 파일을 다른 것으로 간주합니다Package.
대상: aPackage의 요소는 주로 두 가지 유형이 있습니다.

  • 생성된 파일이나 우리가 제공한 원본 파일을 생성할 수 있습니다.

  • 주어진 입력 (원본 파일 또는 생성된 파일) 의 규칙은 출력 (생성된 파일) 을 되돌려줍니다.규칙 출력은 항상 규칙의 동일한 패키지에 속합니다.
  • 인용하다


    파일과 출력을 인용할 수 있는 여러 가지 방법이 있습니다.
    같은 패키지에서 규칙을 참조하려면 콜론:과 규칙 이름을 사용할 수 있습니다.
    a_rule(
        name = "rule_name"
    )
    
    another_rule(
        name = another_rule_name,
        deps = [
            ":rule_name"
        ]
    )
    
    다른 가방을 인용할 때, 우리는 이중 슬래시 (// 를 사용하여 작업 영역의 뿌리에 도달하고, 거기에서 필요한 가방에 도착할 것이다.
    another_package_rule(
        name = "some_name",
        deps = [
            "//foo/bar:a_rule"
        ]
    )
    
    규칙 이름이 패키지 이름과 일치하면 콜론 뒤에 있는 규칙 이름을 생략할 수 있습니다.
    참조 //foo/bar:bar//foo/bar 와 같습니다.

    Bazel 및 Angular


    Bazel은 언어와 프레임워크를 알 수 없는 논자이지만, 우선 Angular와 어떻게 사용하는지, 그리고 무슨 일이 일어났는지 알고 싶습니다.
    필요한 의존 항목을 설치하고 새 프로젝트를 시작합니다.
    npm install -g @angular/bazel
    ng new --collection=@angular/bazel
    
    이 명령은 Bazel이 빌드 도구로 설정된 새 항목을 만듭니다.
    새 프로젝트에 응용 프로그램(ng serve을 제공하면 새 파일이 생성됩니다.
  • /작업공간
  • /건조.바젤
  • .bazelignore
  • .bazelrc
  • /src/BUILD.바젤
  • /e2e/BUILD.바젤
  • CLI가 한 개workspace와 세 개packages를 정의한 것은 확실합니다.패키지 정의에 따라 루트 디렉터리에 있는 패키지는 작업공간에 있는 srce2e 폴더를 제외한 모든 내용을 포함합니다.
    서버를 중지하면 파일이 다시 삭제됩니다.
    그건 zero-config 바젤!
    그러나 만약에 우리가 새로운 라이브러리를 설치했거나 우리의 구축을 최적화하고 싶어서 우리의 구축을 조정해야 한다면 우리는 어떻게 해야 합니까?우리는 수동으로 작업 영역을 만들고 파일을 만들 수도 있고, --leave Bazel Files OnDisk 로고를 사용할 수도 있으며, 이렇게 하면 생성된 파일이 삭제되지 않습니다.
    ng build --leaveBazelFilesOnDisk
    
    구축이 완료되면 생성된 파일을 탐색하거나 수정할 수 있습니다./src/BUILD.bazel부터 시작합시다.나는 설명하기 편리하도록 서류를 몇 부분으로 나눌 것이다.
    package(default_visibility = ["//visibility:public"])
    
    맨 위에서 우리는 가시적 속성을 가지고 있다.가시성 속성은 다른 패키지에서 이 패키지의 규칙에 액세스하거나 액세스하지 못하도록 허용합니다.가시성 범위를 설정할 수 있습니다.이 예에 대해 우리는 그것을 공공으로 보류한다.
    load("@npm_angular_bazel//:index.bzl", "ng_module")
    load("@npm_bazel_karma//:index.bzl", "ts_web_test_suite")
    load("@build_bazel_rules_nodejs//:defs.bzl", "rollup_bundle", "history_server")
    load("@build_bazel_rules_nodejs//internal/web_package:web_package.bzl", "web_package")
    load("@npm_bazel_typescript//:index.bzl", "ts_devserver", "ts_library")
    load("@io_bazel_rules_sass//:defs.bzl", "multi_sass_binary", "sass_binary")
    
    그리고load 명령과 함께 사용할 모든 가져오기.확장에서 기호를 가져옵니다.
    그 다음에 나머지는 규칙과 설정이다.
    sass_binary(
      name = "global_stylesheet",
      src = glob(["styles.css", "styles.scss"])[0],
      output_name = "global_stylesheet.css",
    )
    
    
    multi_sass_binary(
        name = "styles",
        srcs = glob(
          include = ["**/*.scss"],
          exclude = ["styles.scss"],
        ),
    )
    
    
    모든 규칙의 시작에는 그것의 이름이 있다.이것은 우리가 다른 곳에서 그것을 인용할 수 있게 할 것이다. 예를 들어 그것을 다른 규칙의 의존항으로 삼는 것이다.
    첫 번째 규칙은 global_stylesheet 로 명명되었습니다. 이것은 우리가 호출 :global_stylesheet 을 통해 출력에 대한 인용을 얻을 수 있음을 의미합니다.원천은 하나이다.css 또는.scss 파일은 우리의 설정에 달려 있습니다.우리는 출력 파일도 설정했다.
    우리의 두 번째 규칙 styles 은 모든 것을 바꿀 것이다.scss 파일, 전역 스타일 파일은 포함되지 않습니다.
    만약 당신이 (나처럼) CSS를 더 좋아한다면, 우리는 이런 것들에서 벗어날 수 있을 것이다.금방 할게요.
    다음 규칙을 계속합시다.ng_module .
    ng_module(
        name = "src",
        srcs = glob(
            include = ["**/*.ts"],
            exclude = [
                "**/*.spec.ts",
                "main.ts",
                "test.ts",
                "initialize_testbed.ts",
            ],
        ),
        assets = glob([
          "**/*.css",
          "**/*.html",
        ]) + ([":styles"] if len(glob(["**/*.scss"])) else []),
        deps = [
            "@npm//@angular/core",
            "@npm//@angular/platform-browser",
            "@npm//@angular/router",
            "@npm//@types",
            "@npm//rxjs",
        ],
    )
    
    우선, 우리는 규칙을 디렉터리와 같은 이름으로 명명해서 나중에 그것을 인용할 때 더욱 쉽다.주 규칙을 패키지 디렉터리와 같은 이름으로 명명하는 것은 좋은 방법이다.우리는 원본 코드 (모든.ts 파일, 모듈에 속하지 않는 부분을 무시함) 와 자산 (.css와.html 파일을 설정하고 변환된 styles 규칙과 출력 연결을 하고 있습니다.scss 파일).마지막으로 이 예에서 우리는 npm 작업 구역에 있는 의존항을 성명했다.
    rollup_bundle(
        name = "bundle",
        entry_point = ":main.prod.ts",
        deps = [
            "//src",
            "@npm//@angular/router",
            "@npm//rxjs",
        ],
    )
    
    web_package(
        name = "prodapp",
        assets = [
            # do not sort
            "@npm//:node_modules/zone.js/dist/zone.min.js",
            ":bundle.min.js",
            ":global_stylesheet",
        ],
        data = [
            "favicon.ico",
        ],
        index_html = "index.html",
    )
    
    history_server(
        name = "prodserver",
        data = [":prodapp"],
        templated_args = ["src/prodapp"],
    )
    
    filegroup(
        name = "rxjs_umd_modules",
        srcs = [
            # do not sort
            "@npm//:node_modules/rxjs/bundles/rxjs.umd.js",
            ":rxjs_shims.js",
        ],
    )
    
    ts_devserver(
        name = "devserver",
        port = 4200,
        entry_module = "project/src/main.dev",
        serving_path = "/bundle.min.js",
        scripts = [
            "@npm//:node_modules/tslib/tslib.js",
            ":rxjs_umd_modules",
        ],
        static_files = [
            "@npm//:node_modules/zone.js/dist/zone.min.js",
            ":global_stylesheet",
        ],
        data = [
            "favicon.ico",
        ],
        index_html = "index.html",
        deps = [":src"],
    )
    
    ts_library(
        name = "test_lib",
        testonly = 1,
        srcs = glob(["**/*.spec.ts"]),
        deps = [
            ":src",
            "@npm//@angular/core",
            "@npm//@angular/router",
            "@npm//@types",
        ],
    )
    
    ts_library(
        name = "initialize_testbed",
        testonly = 1,
        srcs = [
            "initialize_testbed.ts",
        ],
        deps = [
            "@npm//@angular/core",
            "@npm//@angular/platform-browser-dynamic",
            "@npm//@types",
        ],
    )
    
    ts_web_test_suite(
        name = "test",
        srcs = [
            "@npm//:node_modules/tslib/tslib.js",
        ],
        runtime_deps = [
            ":initialize_testbed",
        ],
        # do not sort
        bootstrap = [
            "@npm//:node_modules/zone.js/dist/zone-testing-bundle.js",
            "@npm//:node_modules/reflect-metadata/Reflect.js",
        ],
        browsers = [
            "@io_bazel_rules_webtesting//browsers:chromium-local",
        ],
        deps = [
            ":rxjs_umd_modules",
            ":test_lib",
            "@npm//karma-jasmine",
        ],
    )
    
    마지막 절은 우리의 번들 프로그램, 개발 서버, 생산 구축과 테스트를 설정하고 설정할 것이다.
    Bazel을 사용할 때, 모든 의존항은 성명되고, 입력과 출력은 이미 알고 있다.이것은 우리가 현재 발생하고 있는 일을 분석하고 방향도를 구축하는 것을 허락할 것이다.우리는query 명령을 사용하여 모든 패키지, 규칙, 저장소와 의존 항목을 조회할 수 있습니다.쿼리 명령은 요청할 수 있는 내용에 매우 표현력이 있으며, 다른 출력 형식을 얻을 수 있습니다.한번 보시겠어요documentation.우리는 또한 도구를 사용하여 조회도 결과를 이미지로 변환할 것이다.
    // get al the packages in the workspace
    bazel query --output=graph ... | dot -Tpng > graph.png
    

    이것은 보기에 너무 많은 정보가 있는 것 같다.다행히도 우리는 도형의 부분을 선택할 수 있다.
    bazel query "kind(rule, allpaths(//src:devserver, //...))" --output=graph | dot -Tpng > devserver.png
    

    우리가 지금 가지고 있는 것을 이용하여 우리의 구축을 최적화하고 맞춤형으로 만들기 시작합시다.우선, 이 항목에 대해 나는 어떤 것도 사용하지 않기로 결정했다.scss 파일, 그래서 나는 styles 규칙에서 벗어날 수 있다.그것에 대한 모든 인용을 삭제하는 것을 기억해라.
    나는 또한 응용 프로그램 디렉터리가 자신의 패키지이기를 희망하기 때문에, 나는 구축을 만들 것이다.bazel 파일.
    package(default_visibility = ["//visibility:public"])
    
    load("@npm_angular_bazel//:index.bzl", "ng_module")
    
    ng_module(
        name = "app",
        srcs = glob(
            include = ["**/*.ts"],
            exclude = ["**/*.spec.ts"],
        ),
        assets = glob([
          "**/*.css",
          "**/*.html",
        ]),
        deps = [
            "@npm//@angular/core",
            "@npm//@angular/platform-browser",
            "@npm//@angular/router",
            "@npm//@types",
            "@npm//rxjs",
        ],
    )
    
    ts_library(
        name = "test_lib",
        testonly = 1,
        srcs = ["app.component.spec.ts"],
        deps = [
            ":app",
            "@npm//@angular/core",
            "@npm//@angular/router",
            "@npm//@types",
        ],
    )
    
    우리는 src/app라는 새 가방app에서 새로운 규칙을 성명했다.우리는 이 가방의 테스트를 처리하기 위한 규칙도 만들었다.
    다음으로 우리는 styles 규칙에 대한 인용을 삭제하고 삭제했다. 반대로 우리는 styles.css 규칙을 원본으로 설정했다.이 밖에 우리는 응용 프로그램 패키지에 테스트에 대한 인용을 추가했다.
    ng_module(
        name = "src",
        srcs = glob(
            include = ["**/*.ts"],
            exclude = [
                "**/*.spec.ts",
                "main.ts",
                "test.ts",
                "initialize_testbed.ts",
            ],
        ),
        assets = glob([
          "**/*.css",
          "**/*.html",
        ]),
        deps = [
            "@npm//@angular/core",
            "@npm//@angular/platform-browser",
            "@npm//@angular/router",
            "@npm//@types",
            "@npm//rxjs",
            "//src/app"
        ],
    )
    
    rollup_bundle(
        name = "bundle",
        entry_point = ":main.prod.ts",
        deps = [
            "//src",
            "@npm//@angular/router",
            "@npm//rxjs",
        ],
    )
    
    web_package(
        name = "prodapp",
        assets = [
            # do not sort
            "@npm//:node_modules/zone.js/dist/zone.min.js",
            ":bundle.min.js",
            "styles.css",
        ],
        data = [
            "favicon.ico",
        ],
        index_html = "index.html",
    )
    
    history_server(
        name = "prodserver",
        data = [":prodapp"],
        templated_args = ["src/prodapp"],
    )
    
    filegroup(
        name = "rxjs_umd_modules",
        srcs = [
            # do not sort
            "@npm//:node_modules/rxjs/bundles/rxjs.umd.js",
            ":rxjs_shims.js",
        ],
    )
    
    ts_devserver(
        name = "devserver",
        port = 4200,
        entry_module = "project/src/main.dev",
        serving_path = "/bundle.min.js",
        scripts = [
            "@npm//:node_modules/tslib/tslib.js",
            ":rxjs_umd_modules",
        ],
        static_files = [
            "@npm//:node_modules/zone.js/dist/zone.min.js",
            "styles.css",
        ],
        data = [
            "favicon.ico",
        ],
        index_html = "index.html",
        deps = [":src"],
    )
    
    ts_library(
        name = "test_lib",
        testonly = 1,
        srcs = glob(["**/*.spec.ts"]),
        deps = [
            ":src",
            "@npm//@angular/core",
            "@npm//@angular/router",
            "@npm//@types",
        ],
    )
    
    ts_library(
        name = "initialize_testbed",
        testonly = 1,
        srcs = [
            "initialize_testbed.ts",
        ],
        deps = [
            "@npm//@angular/core",
            "@npm//@angular/platform-browser-dynamic",
            "@npm//@types",
        ],
    )
    
    ts_web_test_suite(
        name = "test",
        srcs = [
            "@npm//:node_modules/tslib/tslib.js",
        ],
        runtime_deps = [
            ":initialize_testbed",
        ],
        # do not sort
        bootstrap = [
            "@npm//:node_modules/zone.js/dist/zone-testing-bundle.js",
            "@npm//:node_modules/reflect-metadata/Reflect.js",
        ],
        browsers = [
            "@io_bazel_rules_webtesting//browsers:chromium-local",
        ]`
        deps = [
            ":rxjs_umd_modules",
            ":test_lib",
            "//src/app:test_lib",
            "@npm//karma-jasmine",
        ],
    )
    
    만약 우리가 우리의 개발 서버를 다시 분석한다면

    나는 당신의 업무 공간이 늘어나기 시작하면 Bazel을 사용하는 대부분의 장점이 더욱 뚜렷해질 것이라고 믿는다.추가를 시작한 각 모듈의 패턴은 대체로 같다.
    다음은 하나의 예입니다. 저는 핵심 모듈과 다른 두 모듈(사용자, 저장소)에서 사용하는 공유 모듈을 추가했습니다.종속 트리 탐색을 쉽게 시작할 수 있습니다.

    Bazel은 항상 AOT이기 때문에, 모듈을 불러오는 것을 지연시킬 때, 우리는 반드시 공장 모듈을 사용해야 한다는 것을 주의하십시오.
    예:
    const routes: Routes = [
      {
        path: 'users',
        loadChildren: () => import('./users/users.ngfactory').then(m => m.UsersModuleNgFactory)
      },
      {
        path: 'repositories',
        loadChildren: () =>
            import('./repositories/repositories.module.ngfactory').then(m => m.RepositoriesModuleNgFactory)
      }
    ]
    
    만약 당신이 main.dev.tsmain.prod.ts를 자세히 보신다면, 우리도 공장 모듈을 안내하고 있습니다.
    platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);
    
    이제 Bazel을 어떻게 사용하는지에 대한 생각이 생겼습니다. 그 장점에 대해 이야기합시다.
    나는 그들 중 대다수가 대량의 테스트를 통해 대형 코드 라이브러리에 이채를 띠게 될 것이라고 생각한다.다행히도, 그것의 채택은 증가될 수 있으며, 가방은 모든 것을 완성할 수 있으며, 더 구체적인 가방을 만들기 시작하고, 의존 관계를 설명하기 시작할 수 있다.
    원격 구축 및 캐시도 사용할 수 있습니다.주어진 입력 집합에 대해 출력은 항상 같기 때문에 결과를 캐시하고 공유할 수 있습니다.CI가 테스트를 실행한 경우 로컬에서 변경할 때 영향을 받지 않는 테스트의 캐시 결과를 사용하고 영향을 받는 테스트만 실행할 수 있습니다.구축도 그렇고 구축 시간을 줄였다.
    우리는 각도에서만 프로그램을 시작하지만, Bazel은 언어와 무관하기 때문에, 백엔드 (다른 언어로 작성할 수 있음) 를 인용하고, Bazel을 구축 도구로 사용할 수 있습니다.
    비록 Bazel은 확장이 가능하지만, 필요한 규칙을 사용할 수 있도록 많은 일을 했다.따라서 사용자 정의 버전을 작성해야 할 가능성은 낮다.이를 어떻게 하는지 알고 싶으면 파이썬 사투리 Starlark 를 사용하여 규칙을 작성합니다.
    여기에서 소개한 일부 기능은 여전히 Angular Labs의 일부분으로 장래에 변화가 발생할 수 있다.

    공구서류

  • Angular-Bazel guide
  • Bazel docs
  • Angular-Bazel example app
  • 이 문장을 좋아합니까?This Dot Labs로 가서 우리를 살펴보자!우리는 자바스크립트와 전단의 모든 업무에 종사하는 기술 컨설팅 회사입니다.Angular, React 및 Vue 등의 소스 소프트웨어에 집중합니다.

    좋은 웹페이지 즐겨찾기