Cách Angular xây dựng và chạy


84

Bạn chỉ muốn tìm hiểu cách Angular xây dựng và chạy đằng sau hậu trường?

Dưới đây là những gì tôi hiểu cho đến nay. Muốn biết nếu tôi bỏ lỡ điều gì đó.

Cách Angular xây dựng

Sau khi mã hóa các ứng dụng Angular của chúng tôi bằng TypeScript, chúng tôi sử dụng lệnh Angular CLI để xây dựng ứng dụng.

ng buildlệnh biên dịch ứng dụng thành một thư mục đầu ra và các tạo tác xây dựng sẽ được lưu trữ trong dist/thư mục.

Quy trình nội bộ

1. Angular CLI chạy Webpack để xây dựng và đóng gói tất cả mã JavaScript và CSS.

2. Đến lượt nó, Webpack gọi trình tải TypeScript tìm nạp tất cả .tstệp trong dự án Angular và sau đó chuyển chúng sang JavaScript tức là thành một .jstệp mà trình duyệt có thể hiểu được.

Bài đăng này cho biết Angular có hai trình biên dịch:

  • Xem trình biên dịch

  • Trình biên dịch mô-đun

Câu hỏi về các bản dựng

Trình tự gọi quá trình xây dựng là gì?

Angular CLI đầu tiên gọi trình biên dịch tích hợp sẵn Angular viết bằng TypeScript => sau đó gọi TypeScript Transpiler => sau đó gọi Webpack để đóng gói và lưu trữ trong dist/thư mục.

Cách Angular chạy

Khi quá trình xây dựng hoàn tất, tất cả các thành phần, dịch vụ, mô-đun, v.v. của ứng dụng của chúng tôi được chuyển sang JavaScript .jstệp được sử dụng để chạy ứng dụng Angular trong trình duyệt.

Các câu lệnh trong Angular Docs

  1. Khi bạn khởi động với AppComponentlớp (trong main.ts), Angular sẽ tìm kiếm một <app-root>trong đó index.html, tìm thấy nó, khởi tạo một phiên bản của AppComponent và hiển thị nó bên trong <app-root>thẻ.

  2. Angular tạo, cập nhật và hủy các thành phần khi người dùng di chuyển qua ứng dụng.

Câu hỏi khi chạy

Mặc dù main.tsđược sử dụng trong câu lệnh ở trên để giải thích quá trình khởi động, nhưng không phải ứng dụng Angular đã được khởi động hoặc bắt đầu sử dụng .jstệp JavaScript ?

Không phải tất cả các câu lệnh trên đều được thực hiện trong thời gian chạy bằng .jscác tệp JavaScript ?

Có ai biết làm thế nào tất cả các bộ phận phù hợp với nhau về chiều sâu?

Câu trả lời:


89

(Khi tôi nói Angular, tôi có nghĩa là Angular 2+ và sẽ nói rõ ràng là angle-js nếu tôi đang đề cập đến góc 1).

Khúc dạo đầu: Thật là khó hiểu

Angular, và có lẽ chính xác hơn là angle-cli đã hợp nhất một số công cụ thịnh hành trong Javascript tham gia vào quá trình xây dựng. Nó dẫn đến một chút nhầm lẫn.

Để gây nhầm lẫn thêm, thuật ngữ compilenày thường được sử dụng trong angle-js để chỉ quá trình lấy html giả của mẫu và biến nó thành các phần tử DOM. Đó là một phần của những gì trình biên dịch làm nhưng là một trong những phần nhỏ hơn.

Trước hết, không cần sử dụng TypeScript, angle-cli hoặc Webpack để chạy Angular. Để trả lời câu hỏi của bạn. Chúng ta nên xem xét một câu hỏi đơn giản: "Angular là gì?"

Angular: Nó làm gì?

Phần này có thể gây tranh cãi, chúng ta sẽ xem. Về cốt lõi, dịch vụ mà Angular cung cấp là một cơ chế chèn phụ thuộc hoạt động trên Javascript, HTML và CSS. Bạn viết tất cả các mẩu nhỏ và từng mẩu riêng lẻ và trong mỗi mẩu nhỏ, bạn tuân theo các quy tắc của Angular để tham khảo các mẩu khác. Angular sau đó dệt nên hoàn toàn bằng cách nào đó.

Cụ thể hơn (một chút):

  • Các mẫu cho phép HTML được kết nối với thành phần Javascript. Điều này cho phép đầu vào của người dùng trên chính DOM (ví dụ: nhấp vào nút) để đưa vào thành phần Javascript và cũng cho phép các biến trong thành phần Javascript kiểm soát cấu trúc và giá trị trong DOM.
  • Các lớp Javascript (bao gồm các thành phần Javascript) cần có khả năng truy cập các phiên bản của các lớp Javascript khác mà chúng phụ thuộc vào (ví dụ: chèn phụ thuộc cổ điển). BookListComponent cần một phiên bản BookListService có thể cần một phiên bản BookListPolicy hoặc một cái gì đó tương tự. Mỗi lớp này có vòng đời khác nhau (ví dụ: các dịch vụ thường là các lớp đơn, các thành phần thường không phải là lớp con) và Angular phải quản lý tất cả các vòng đời đó, việc tạo ra các thành phần và đi dây của các phần phụ thuộc.
  • Các quy tắc CSS cần được tải theo cách mà chúng chỉ áp dụng cho một tập hợp con của DOM (kiểu của một thành phần là cục bộ cho thành phần đó).

Một điều quan trọng cần lưu ý là Angular không chịu trách nhiệm về cách các tệp Javascript tham chiếu đến các tệp Javascript khác (ví dụ: importtừ khóa). Điều đó do Webpack đảm nhận.

Trình biên dịch làm gì?

Bây giờ bạn đã biết Angular là gì, chúng ta có thể nói về những gì trình biên dịch làm. Tôi sẽ tránh quá kỹ thuật chủ yếu vì tôi không biết gì. Tuy nhiên, trong một hệ thống dependency injection bạn thường phải thể hiện sự phụ thuộc của bạn với một số loại siêu dữ liệu (ví dụ như thế nào có tiếng nói lớp I can be injected, My lifetime is blahhoặc You can think of me as a Component type of instance). Trong Java, Spring ban đầu đã làm điều này với các tệp XML. Java sau đó đã áp dụng các chú thích và chúng đã trở thành cách ưa thích để thể hiện siêu dữ liệu. C # sử dụng các thuộc tính để thể hiện siêu dữ liệu.

Javascript không có một cơ chế tuyệt vời để hiển thị nội trang siêu dữ liệu này. angle-js đã cố gắng và nó không tệ nhưng có rất nhiều quy tắc không thể dễ dàng kiểm tra và hơi khó hiểu. Với Angular, có hai cách được hỗ trợ để chỉ định siêu dữ liệu. Bạn có thể viết Javascript thuần túy và chỉ định siêu dữ liệu theo cách thủ công, hơi giống với angle-js và chỉ cần tuân theo các quy tắc và viết thêm mã boiler-platey. Ngoài ra, bạn có thể chuyển sang TypeScript, khi nó xảy ra, có các trình trang trí (những @ký hiệu đó) được sử dụng để thể hiện siêu dữ liệu.

Vì vậy, đây là nơi cuối cùng chúng ta có thể đến trình biên dịch. Công việc của trình biên dịch là lấy siêu dữ liệu đó và tạo ra hệ thống các phần làm việc chính là ứng dụng của bạn. Bạn tập trung vào tất cả các phần và tất cả siêu dữ liệu và trình biên dịch sẽ xây dựng một ứng dụng lớn được kết nối với nhau.

Trình biên dịch làm điều đó như thế nào?

Có hai cách trình biên dịch có thể hoạt động, thời gian chạy và tính năng vượt thời gian. Từ đây trở đi, tôi sẽ giả sử bạn đang sử dụng TypeScript:

  • Thời gian chạy: Khi trình biên dịch typecript chạy, nó sẽ lấy tất cả thông tin của decorator và chuyển nó vào mã Javascript được đính kèm với các lớp, phương thức và trường được trang trí. Trong bạn, index.htmlbạn tham khảo của bạn main.jsmà gọi bootstrapphương thức. Phương pháp đó được thông qua mô-đun cấp cao nhất của bạn.

Phương thức bootstrap kích hoạt trình biên dịch thời gian chạy và cung cấp cho nó một tham chiếu đến mô-đun cấp cao nhất đó. Sau đó, trình biên dịch thời gian chạy bắt đầu thu thập dữ liệu mô-đun đó, tất cả các dịch vụ, thành phần, v.v. được mô-đun đó tham chiếu và tất cả siêu dữ liệu được liên kết và xây dựng ứng dụng của bạn.

  • LƯU Ý: Thay vì thực hiện tất cả công việc trong thời gian chạy, Angular đã cung cấp một cơ chế để thực hiện hầu hết công việc tại thời điểm xây dựng. Điều này hầu như luôn được thực hiện bằng cách sử dụng plugin webpack (đây phải là một trong những gói npm phổ biến nhất nhưng ít được biết đến nhất). Nó chạy sau khi quá trình biên dịch typecript chạy nên về cơ bản nó thấy đầu vào giống với trình biên dịch thời gian chạy. Trình biên dịch AOT xây dựng ứng dụng của bạn giống như trình biên dịch thời gian chạy nhưng sau đó lưu lại thành Javascript.

Ưu điểm ở đây không chỉ là bạn có thể tiết kiệm thời gian CPU cần thiết cho quá trình biên dịch mà còn cho phép bạn giảm dung lượng ứng dụng của mình.

Câu trả lời cụ thể

Angular CLI Đầu tiên gọi trình biên dịch được xây dựng trong góc độ được viết bằng Typecript => sau đó gọi Trình chuyển đổi kiểu chữ => sau đó gọi Webpack để đóng gói và lưu trữ trong thư mục dist /.

Không. Angular CLI gọi Webpack (Dịch vụ thực của Angular CLI đang định cấu hình webpack. Khi bạn chạy ng buildnó không nhiều hơn một proxy để khởi động Webpack). Đầu tiên, Webpack gọi trình biên dịch Typecript, sau đó là trình biên dịch góc (giả sử là AOT), tất cả trong khi gói mã của bạn cùng một lúc.

Mặc dù main.ts được sử dụng trong Tuyên bố ở trên để giải thích quy trình bootstrap, Ứng dụng angle không được khởi động hoặc bắt đầu sử dụng tệp .js Javascript?

Tôi không hoàn toàn chắc chắn những gì bạn đang hỏi ở đây. main.tssẽ được chuyển xuống Javascript. Javascript đó sẽ chứa một lời gọi bootstraplà điểm vào Angular. Khi bootstraphoàn tất, bạn sẽ có ứng dụng Angular đầy đủ của mình đang chạy.

Bài đăng này cho biết Angular có hai trình biên dịch:

Xem trình biên dịch

Trình biên dịch mô-đun

Thành thật mà nói, tôi sẽ chỉ tuyên bố sự thiếu hiểu biết ở đây. Tôi nghĩ ở cấp độ của chúng ta, chúng ta có thể coi tất cả như một trình biên dịch lớn.

Có ai biết làm thế nào tất cả các bộ phận phù hợp với nhau về chiều sâu?

Tôi hy vọng ở trên thỏa mãn điều này.

Đừng @ Tôi: Angular làm nhiều hơn là tiêm phụ thuộc

Chắc chắn rồi. Nó thực hiện định tuyến, xây dựng chế độ xem, phát hiện thay đổi và tất cả các loại khác. Trình biên dịch thực sự tạo ra Javascript để xây dựng chế độ xem và phát hiện thay đổi. Tôi đã nói dối khi nói rằng đó chỉ là tiêm thuốc phụ thuộc. Tuy nhiên, phần phụ thuộc là cốt lõi và đủ để thúc đẩy phần còn lại của câu trả lời.

Chúng ta có nên gọi nó là một trình biên dịch không?

Nó có thể thực hiện rất nhiều phân tích cú pháp và ghép từ và chắc chắn tạo ra rất nhiều mã do đó bạn có thể gọi nó là một trình biên dịch vì lý do đó.

Mặt khác, nó không thực sự dịch mã của bạn thành một biểu diễn khác. Thay vào đó, nó là lấy một loạt các đoạn mã khác nhau và dệt chúng thành các mảnh có thể tiêu thụ được của một hệ thống lớn hơn. Quá trình bootstrap sau đó (sau khi biên dịch, nếu cần) sẽ lấy những phần đó và cắm chúng vào lõi Angular.


Cảm ơn bạn đã trả lời chi tiết. Trước khi chấp nhận câu trả lời của bạn, tôi nghi ngờ trong Tuyên bố của Bạn The compiler does actually generate Javascript` để xây dựng chế độ xem và phát hiện thay đổi. `Đó không phải là một lời nói dối. Đó là những gì trình biên dịch không? Và góc cạnh không tiêm phụ thuộc.
shaijut

1
Vâng xin lôi. lời nói dối mà tôi đề cập đến là “Về cốt lõi, dịch vụ mà Angular cung cấp, là một cơ chế tiêm phụ thuộc” bởi vì trong khi Angular làm điều đó thì nó không phải là tất cả những gì nó làm và thậm chí không phải tất cả những gì trình biên dịch làm.
Pace

Nếu Angular được trừu tượng hóa như một "ngôn ngữ" mới với các tính năng như thành phần, chỉ thị, dịch vụ, v.v. Nó có thể được gọi là một trình biên dịch. Hợp nhất ngôn ngữ Angular thành js và html thô.
Chris Bao,

10

Hãy để tôi bắt đầu lại từ đầu.

Trong ứng dụng của tôi, tôi trực tiếp chạy ứng dụng từ đó Webpack.

Để xây dựng và chạy ứng dụng, chúng tôi sử dụng lệnh webpack --progresswebpack-dev-server --inline, lệnh này đã được viết package.jsondưới đây

"scripts": {
    "serve": "webpack-dev-server --inline ",
    "build": "webpack --progress"

  }

Khi chúng tôi chạy webpack --progresslệnh, nó bắt đầu đọc webpack.config.jstệp nơi nó tìm thấy điểm nhập như bên dưới.

module.exports = {
    devtool: 'source-map',
    entry: './src/main.ts',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.ts$/,
                loaders: ['awesome-typescript-loader', 'angular2-template-loader'],
                exclude: [/\.(spec|e2e)\.ts$/]
            },
            /* Embed files. */
            {
                test: /\.(html|css)$/,
                loader: 'raw-loader',
                exclude: /\.async\.(html|css)$/
            },
            /* Async loading. */
            {
                test: /\.async\.(html|css)$/,
                loaders: ['file?name=[name].[hash].[ext]', 'extract']
            },
        ]
    },
    resolve: {
        extensions: ['.ts', '.js']
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        })
    ]
}   

và sau đó nó đọc tất cả Typescripttệp và biên dịch dựa trên các quy tắc được khai báo trong tsconfig.jsontệp và hơn là chuyển đổi nó thành các .jstệp tương ứng và đó là tệp bản đồ.

Nếu nó chạy mà không có bất kỳ lỗi biên dịch nào, nó sẽ tạo bundle.jstệp có tên như chúng ta đã khai báo trong phần Webpackđầu ra.

Bây giờ hãy để tôi giải thích lý do tại sao chúng tôi sử dụng bộ nạp.

awesome-typecript-loader, angle2-template-loader Chúng tôi sử dụng các trình tải này để biên dịch Typescripttệp trên cơ sở được khai báo trong tsconfig.jsontệp và angle2-template-loader tìm kiếm templateUrlstyleUrlskhai báo bên trong siêu dữ liệu Thành phần Angular 2 và thay thế các đường dẫn bằng câu lệnh yêu cầu.

resolve: {
        extensions: ['.ts', '.js']
    }

Chúng tôi sử dụng phần giải quyết ở trên để yêu Webpackcầu chuyển đổi Typescriptthành JavaScripttệp

plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        })
    ]

Phần plugin được sử dụng để chèn khuôn khổ hoặc tệp của bên thứ ba. Trong mã của tôi, tôi đang sử dụng cái này để đưa vào index.htmlthư mục đích.

 devtool: 'source-map',

Dòng trên được sử dụng để xem Typescripttệp trong trình duyệt và gỡ lỗi nó chủ yếu được sử dụng cho mã nhà phát triển.

 loader: 'raw-loader'

Trên đây raw-loaderđược sử dụng để nạp .html.csstập tin và đóng gói lại cùng với Typescripttập tin.

Vào cuối khi chúng tôi chạy webpack-dev-server - trong dòng nó sẽ tạo máy chủ riêng và khởi động ứng dụng theo đường dẫn được đề cập trong web-pack.config.jstệp mà chúng tôi đã đề cập đến thư mục đích và điểm nhập.

Trong Angular2 điểm đầu vào của hầu hết các ứng dụng là main.tsnơi chúng ta đề cập đến mô-đun bootstrap ban đầu, ví dụ (app.module) mô-đun này chứa thông tin ứng dụng đầy đủ như tất cả chỉ thị, dịch vụ, mô-đun, thành phần và việc thực hiện định tuyến của toàn bộ ứng dụng.

Lưu ý: Nhiều người thắc mắc rằng tại sao index.htmlchỉ khởi động được ứng dụng, mặc dù họ không hề đề cập đến chỗ nào. Câu trả lời là khi Webpacklệnh serve chạy nó tạo ra lệnh phục vụ riêng và theo mặc định nó sẽ tải index.htmlnếu bạn chưa đề cập đến trang mặc định nào.

Tôi hy vọng rằng thông tin đưa ra sẽ giúp một số người.


1
Đánh giá cao bạn đã cố gắng giải thích, Sẽ tốt hơn nếu bạn có thể giải thích theo trình tự rõ ràng hơn. Vì vậy, bạn không sử dụng Angular CLIđể xây dựng Angularứng dụng và sử dụng Webpacktrực tiếp như thế nào?
shaijut

5

Angular xây dựng như thế nào?

Các Angular CLIcuộc gọi Webpack, khi Webpacktruy cập vào một .tstệp, nó sẽ chuyển nó đến TypeScriptTrình biên dịch có một biến áp đầu ra để biên dịch các Angularmẫu

Vì vậy, trình tự xây dựng là:

Angular CLI=> Webpack=> TypeScriptTrình biên dịch => TypeScriptTrình biên dịch gọi Angulartrình biên dịch trong thời gian biên dịch.

Angular chạy như thế nào?

Angularkhởi động và chạy bằng Javascripttệp.

Thực ra quá trình bootstrap là thời gian chạy và xảy ra trước khi mở trình duyệt. Điều này đưa chúng ta đến câu hỏi tiếp theo của chúng ta.

Vì vậy, Nếu quá trình bootstrap xảy ra với Javascripttệp thì tại sao AngularDocs lại sử dụng main.tstệp TypeScript để giải thích quá trình bootstrap?

AngularTài liệu chỉ nói về các .tstệp vì đó là nguồn.

Đây là câu trả lời ngắn gọn. Đánh giá cao nếu bất cứ ai có thể trả lời sâu.

Tín dụng chuyển đến @ Toxicable để trả lời các câu hỏi của tôi trong cuộc trò chuyện.


2

Có thể là muộn cho câu trả lời này, nhưng gần đây đã có một cuộc nói chuyện thực sự hay về chủ đề này, bắt đầu từ quan điểm mới bắt đầu và đi sâu hơn. Thay vì cố gắng tóm tắt hoặc chỉ ra thông tin sai lệch trong chủ đề này bằng lời nói của tôi, tôi sẽ chỉ liên kết video của Kara Erickson: Cách hoạt động của Angular .

Cô ấy là trưởng nhóm công nghệ về khung công tác Angular và có một bài thuyết trình thực sự tốt về:

  • các phần chính của khung Angular là gì
  • trình biên dịch hoạt động như thế nào, nó tạo ra cái gì
  • "Định nghĩa thành phần" là gì
  • Bootstrap ứng dụng là gì, nó hoạt động như thế nào

1
Cảm ơn bạn đã đóng góp :), Đánh giá cao.
shaijut

1

Vì vậy, Nếu quá trình bootstrap xảy ra với tệp Javascript thì tại sao Angular Docs lại sử dụng tệp main.ts TypeScript để giải thích quá trình bootstrap?

Đây là một phần của phiên bản .js đã biến đổi của main.ts được phát ra bởi ng buildnó chưa được xác minh và rút gọn, Bạn mong đợi người mới bắt đầu có thể hiểu được mã này như thế nào? nó trông có vẻ phức tạp không?

Object(__WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_dynamic__["a" /* platformBrowserDynamic */])().bootstrapModule(__WEBPACK_IMPORTED_MODULE_2__app_app_module__["a" /* AppModule */])
    .catch(function (err) { return console.log(err); });

và với việc ng build --prod --build-optimizerlàm xấu và thu nhỏ mã của bạn để tối ưu hóa nó, các gói được tạo sẽ nhỏ gọn và ở định dạng bit khó đọc.

webpackJsonp([1],{0:function(t,e,n){t.exports=n("cDNt")},"1j/l":function(t,e,n){"use strict";n.d(e,"a",function(){return r});var r=Array.isArray||function(t){return t&&"number"==typeof t.length}},"2kLc

trong khi tệp main.ts là con người có thể đọc được và sáng suốt, đó là lý do tại sao angle.io sử dụng main.ts để giải thích quá trình bootstrap của ứng dụng angle. Angular: Tại sao nên sử dụng TypeScript? ngoài điều này nếu bạn là tác giả của một khuôn khổ tuyệt vời như vậy, bạn sẽ sử dụng cách tiếp cận nào để làm cho khuôn khổ của mình trở nên phổ biến và thân thiện với người dùng? bạn sẽ không đi tìm lời giải thích rõ ràng và ngắn gọn hơn là một lời giải thích phức tạp? Tôi đồng ý rằng tài liệu của angle.io thiếu lời giải thích chuyên sâu và nó không hoàn toàn tuyệt vời nhưng cho đến nay tôi thấy họ đang nỗ lực để làm cho nó tốt hơn.


1

Angular 9+ sử dụng AOT (Ahead of Time Compilation) có nghĩa là nó lấy tất cả các bit nằm rải rác trong các tệp khác nhau, tức là thành phần (.ts + .html + .css), mô-đun (.ts) và xây dựng JavaScript dễ hiểu của trình duyệt được tải xuống trong thời gian chạy và được thực thi bởi trình duyệt.

Trước Angular 9, nó là JIT (Just in time Compilation), nơi mã được biên dịch theo yêu cầu của trình duyệt.

Để biết chi tiết, hãy xem: Angular AOT Documentaiton

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.