Sử dụng Webpack trong Angular 2
Bài đăng này đã không được cập nhật trong 7 năm
1. Webpack là gì ?
Webpack là một module bundler cho những ứng dụng javascript hiện đại. Bundle là quá trình gom (hay còn gọi là nén) các tài nguyên khác nhau (source code) vào một file duy nhất sau đó sẽ trả về client. Bundle có thể bao gồm javascript, css, html và hầu hết các loại file khác. Đồng thời, nó cũng có những ứng dụng khá tương đồng với các thư viện khác như: RequireJs, SystemJs,..Kết hợp với một số plugin nó có thể xử lý và nén các loại file như: Typescript, SASS, và LESS. Dưới đây là một số khái niệm quan trọng của Webpack.
1.1 Entry
Webpack tạo ra một đồ thị của toàn bộ những phụ thuộc trong ứng dụng của bạn. Điểm bắt đầu của đồ thị này được gọi là một entry. Entry nói cho Webpack nơi để bắt đầu và theo dõi các phụ thuộc để biết được cái gì cần bundle. Hoặc bạn có thể hiểu entry như file đầu tiên để khởi động app.
webpack.config.js
module.exports = {
entry: './path/to/my/entry/app.js'
};
1.2 Output
Đây là nơi chỉ cho Webpack cần lưu trữ khi hoàn thành quá trình bundle
webpack.config.js
module.exports = {
entry: './path/to/my/entry/app.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'output.bundle.js'
}
};
1.3 Loaders
Loader in webpack chuyển đổi những file .css, .html, .jpg,.. đến những modules mà chúng được thêm trong đồ thị sự phụ thuộc. Chúng có 2 mục đích chính trong config:
- Xác định những file nào nên được chuyển đổi bởi loader nào.
- Chuyển đổi file đó để làm sao nó có thể thêm vào đồ thị sự phụ thuộc.
webpack.config.js
const config = {
entry: './path/to/my/entry/app.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'output.bundle.js'
},
module: {
rules: [
{test: /\.(js|jsx)$/, use: 'babel-loader'}
]
}
};
1.4 Plugins
Plusgins được sử dụng phổ biến nhất là để thực hiện bước cập nhật, biên tập các modules đã được bundle:
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
const config = {
entry: './path/to/my/entry/app.js',
output: {
filename: 'output.bundle.js',
path: './dist'
},
module: {
rules: [
{test: /\.(js|jsx)$/, use: 'babel-loader'}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
module.exports = config;
2. Sử dụng Webpack trong Angular 2
- Configure Webpack
Tạo thư mục project mới
mkdir angular-webpack
cd angular-webpack
Thêm một số file sau vào project:
package.json
{
"name": "angular2-webpack",
"version": "1.0.0",
"description": "A webpack starter for Angular",
"scripts": {
"start": "webpack-dev-server --inline --progress --port 8080",
"test": "karma start",
"build": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail"
},
"license": "MIT",
"dependencies": {
"@angular/common": "~2.2.0",
"@angular/compiler": "~2.2.0",
"@angular/core": "~2.2.0",
"@angular/forms": "~2.2.0",
"@angular/http": "~2.2.0",
"@angular/platform-browser": "~2.2.0",
"@angular/platform-browser-dynamic": "~2.2.0",
"@angular/router": "~3.2.0",
"core-js": "^2.4.1",
"rxjs": "5.0.0-beta.12",
"zone.js": "^0.6.25"
},
"devDependencies": {
"@types/node": "^6.0.45",
"@types/jasmine": "^2.5.35",
"angular2-template-loader": "^0.4.0",
"awesome-typescript-loader": "^2.2.4",
"css-loader": "^0.23.1",
"extract-text-webpack-plugin": "^1.0.1",
...
}
}
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true
}
}
webpack.config.js
module.exports = require('./config/webpack.dev.js');
config/helpers.js
var path = require('path');
var _root = path.resolve(__dirname, '..');
function root(args) {
args = Array.prototype.slice.call(arguments, 0);
return path.join.apply(path, [_root].concat(args));
}
exports.root = root;
config/webpack.common.js
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');
module.exports = {
entry: {
'polyfills': './src/polyfills.ts',
'vendor': './src/vendor.ts',
'app': './src/main.ts'
},
resolve: {
extensions: ['', '.ts', '.js']
},
module: {
loaders: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'html'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file?name=assets/[name].[hash].[ext]'
},
{
test: /\.css$/,
exclude: helpers.root('src', 'app'),
loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
},
{
test: /\.css$/,
include: helpers.root('src', 'app'),
loader: 'raw'
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: ['app', 'vendor', 'polyfills']
}),
new HtmlWebpackPlugin({
template: 'src/index.html'
})
]
};
- Các common configurations
entry: {
'polyfills': './src/polyfills.ts',
'vendor': './src/vendor.ts',
'app': './src/main.ts'
},
Chúng ta đang chia ứng dụng tới 3 bundlers:
- polyfills - các polyfills chuẩn chúng ta yêu cầu để chạy ứng dụng Angular trong hầu hết các trình duyệt hiện đại.
- vendor - các files vendor chúng ta cần: Angular, lodash, bootstrap.css...
- app - code ứng dụng.
resolve: {
extensions: ['', '.ts', '.js']
},
Điều này nói cho webpack biết để resovle các files có extension match với biểu thức trên. Như vậy bạn có thể sử dụng
import { AppComponent } from './app.component.ts';
Hoặc
import { AppComponent } from './app.component';
Chỉ định loader:
module: {
loaders: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'html'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file?name=assets/[name].[hash].[ext]'
},
{
test: /\.css$/,
exclude: helpers.root('src', 'app'),
loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
},
{
test: /\.css$/,
include: helpers.root('src', 'app'),
loader: 'raw'
}
]
},
- awesome-typescript-loader - một loader để transpile code Typescript tới ES5.
- angular2-template-loader - tải template của component và styles.
- html - Cho template của component
- images/fonts - Images và fonts cũng được bundle.
- css - Cho css file
Thêm plugin
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: ['app', 'vendor', 'polyfills']
}),
new HtmlWebpackPlugin({
template: 'src/index.html'
})
]
Ngoài ra còn một số config tôi không trình bày ở đây như: Environment, Test configuration.
- Tạo view, component
src/index.html
<!DOCTYPE html>
<html>
<head>
<base href="/">
<title>Angular With Webpack</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>
src/main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app/app.module';
if (process.env.ENV === 'production') {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule);
src/app/app.component.ts
import { Component } from '@angular/core';
import '../../public/css/styles.css';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent { }
src/app/app.component.html
<main>
<h1>Hello from Angular App with Webpack</h1>
<img src="../../public/images/angular.png">
</main>
Các bạn có thể xem code đầy đủ tại link sau:
Điểm nổi bật:
-
Không có thẻ <script> hoặc thẻ <link> trong indexex.html. "HtmlWebpackPlugin" chèn chúng tự động tại runtime.
-
AppComponent trong app.component.ts import css như những module javascript
-
AppComponent có file html và css của riếng nó. Webpack tải chúng với việc gọi reqired(). Chúng ta không hề thấy những công việc này trong source code, chúng được thêm bên trong plugin "angular2-template-loader"
-
Vendor.ts bao gồm những những câu lệnh import các dependency để đưa tới file vendor.js. Ứng dụng cũng import những module này. Như vậy, sẽ có trùng lặp trong file app.js sau khi bundle. "CommonsChunkPlugin" thực hiện việc phát hiện và gỡ bỏ những trùng lặp này.
3. Kết luận
Hy vọng những nội dung trên đây sẽ đóp góp những hiểu biết cơ bản nhất dành cho các bạn về Webpack và sử dụng nó trong Angular 2. Chúc các bạn thành công.
Link tham khảo:
All rights reserved