Webpack Html-loader 不在 bundle 中添加模板
Webpack Html-loader does not add template in bundle
我在使用 Angular (4.4.4
) 和 Webpack (3.6.0
) 创建入门项目时遇到问题。我的配置在 component
中使用 AOT 构建和 template
声明,但是只要我添加 html 模板(并将 template
替换为 templateUrl
) Webpack 进入无限循环并卡在 95% emtitting
。我正在使用 html-loader V0.5.1
进行模板加载
webpack.common.js
module.exports = {
entry: {
app: './src/main.ts',
vendor: getVendorPackages()
},
output: {
path: __dirname + '/dist',
filename: "app.bundle.js"
},
module: {
loaders: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'html-loader'
}
]
},
plugins: [
new webpack.ContextReplacementPlugin( //Resolve Angular warnings
/angular(\|\/)core(\|\/)@angular/,
path.resolve(__dirname, '../src')
),
new webpack.optimize.CommonsChunkPlugin({ //Create secondary bundle containing dependencies
name: 'vendor',
filename: 'vendor.bundle.js',
minChunks(module) {
const context = module.context;
return context && context.indexOf('node_modules') >= 0;
},
}),
new htmlWebpackPlugin({ //Generate index.html
template: './src/index.html'
}),
new webpack.ContextReplacementPlugin( //Only export the locals we need | https://github.com/moment/moment/issues/2517
/moment[\/\]locale$/, /en|nl/
)
],
resolve: {
extensions: ['.js', '.ts']
}
};
app.component.ts
import {Component} from '@angular/core';
@Component({
selector: 'hn-root',
// template: `<h1>Hello world</h1>`
templateUrl: 'app.html',
// styleUrls: ['./app.scss']
})
export class AppComponent {
}
app.html
<h1>Hello big world</h1>
package.json
{
"name": "angular-webpack-starter",
"version": "0.1.0",
"scripts": {
"build": "webpack --config webpack.dev.js",
"serve": "webpack-dev-server --config webpack.dev.js",
"build --prod": "webpack -p --config webpack.prod.js --progress"
},
"dependencies": {
"@angular/common": "4.4.4",
"@angular/compiler": "4.4.4",
"@angular/core": "4.4.4",
"@angular/forms": "4.4.4",
"@angular/http": "4.4.4",
"@angular/platform-browser": "4.4.4",
"@angular/platform-browser-dynamic": "4.4.4",
"@angular/router": "4.4.4",
"core-js": "2.5.1",
"reflect-metadata": "0.1.10",
"rxjs": "5.4.3",
"zone.js": "0.8.18"
},
"devDependencies": {
"@angular/compiler-cli": "4.4.4",
"@ngtools/webpack": "1.7.2",
"@types/core-js": "0.9.43",
"@types/node": "8.0.31",
"angular2-template-loader": "0.6.2",
"awesome-typescript-loader": "3.2.3",
"codelyzer": "3.2.0",
"html-loader": "0.5.1",
"html-webpack-plugin": "2.30.1",
"tslint": "5.7.0",
"typescript": "2.5.3",
"webpack": "3.6.0",
"webpack-bundle-analyzer": "2.9.0",
"webpack-dev-server": "2.9.1",
"webpack-merge": "4.1.0"
}
}
我显然做错了什么,但我不知道那是什么..
我试过了
正在将 templateUrl
更改为 './app.html'
将 app.html
更改为 app.component.html
(angular 约定)
正在将 loaders:[angular2-template-loader]
更改为 loaders:[angular2-template-loader?keepUrl=true]
我还检查了大多数 angular 初学者(包括 angular-cli)的 webpack.config.js,他们使用 raw-loader
而不是 html-loader
。让我想知道,html-loader
是否可以与 AOT compilation
结合使用,因为它会创建内联 html?
为了回答我自己的问题,我在 webpack.common.js 中犯了一个错误。我在应该使用密钥 rules
.
的地方使用了密钥 loaders
因此新代码将是:
module.exports = {
entry: {
app: './src/main.ts',
vendor: getVendorPackages()
},
output: {
path: __dirname + '/dist',
filename: "website.bundle.js"
},
module: {
rules: [
{
test: /\.html$/,
loader: 'html-loader'
}
]
},
plugins: [
new webpack.ContextReplacementPlugin( //Resolve Angular warnings
/angular(\|\/)core(\|\/)@angular/,
path.resolve(__dirname, '../src')
),
new webpack.optimize.CommonsChunkPlugin({ //Create secondary bundle containing dependencies
name: 'vendor',
filename: 'vendor.bundle.js',
minChunks(module) {
const context = module.context;
return context && context.indexOf('node_modules') >= 0;
},
}),
new htmlWebpackPlugin({ //Generate index.html
template: './src/index.html'
}),
new webpack.ContextReplacementPlugin( //Only export the locals we need | https://github.com/moment/moment/issues/2517
/moment[\/\]locale$/, /en|nl/
)
],
resolve: {
extensions: ['.js', '.ts']
}
};
或更具体:
module: {
rules: [
{
test: /\.html$/,
loader: 'html-loader'
}
]
},
您可能还会注意到 /\.ts$/
规则已消失。这是因为 AOT 编译使用它自己的 typescript 编译器并且 webpack-merge
不会覆盖规则。因此,我不得不将编译向下移动到开发配置:
webpack.dev.ts
module.exports = merge(common, {
module: {
rules: [
{
test: /\.ts$/, //Prod uses AOT for .ts and webpack does not override the rules, so they need to be separated
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
]
},
plugins: [
new BundleAnalyzerPlugin({ //Make bundle sizes visible
analyzerMode: 'static',
openAnalyzer: false
}),
new webpack.DefinePlugin({ //Set the node env so that the project knows what to enable or disable
'process.env': {
'NODE_ENV': JSON.stringify('development')
}
})
],
devtool: 'eval-source-map',
});
为了扩展我的答案并制作一个工作示例(使用 AOT 编译),我还必须向我的 tsconfig.json
添加一些数据(参见 AOT documentation):
"files": [
"src/app/app.module.ts",
"src/main.ts"
],
"angularCompilerOptions": {
"genDir": "aot",
"skipMetadataEmit" : true
}
合并后得到以下 tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"module": "es2015",
"moduleResolution": "node",
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"removeComments": false,
"sourceMap": true,
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
]
},
"files": [
"src/app/app.module.ts",
"src/main.ts"
],
"angularCompilerOptions": {
"genDir": "aot",
"skipMetadataEmit" : true
}
}
我在使用 Angular (4.4.4
) 和 Webpack (3.6.0
) 创建入门项目时遇到问题。我的配置在 component
中使用 AOT 构建和 template
声明,但是只要我添加 html 模板(并将 template
替换为 templateUrl
) Webpack 进入无限循环并卡在 95% emtitting
。我正在使用 html-loader V0.5.1
进行模板加载
webpack.common.js
module.exports = {
entry: {
app: './src/main.ts',
vendor: getVendorPackages()
},
output: {
path: __dirname + '/dist',
filename: "app.bundle.js"
},
module: {
loaders: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'html-loader'
}
]
},
plugins: [
new webpack.ContextReplacementPlugin( //Resolve Angular warnings
/angular(\|\/)core(\|\/)@angular/,
path.resolve(__dirname, '../src')
),
new webpack.optimize.CommonsChunkPlugin({ //Create secondary bundle containing dependencies
name: 'vendor',
filename: 'vendor.bundle.js',
minChunks(module) {
const context = module.context;
return context && context.indexOf('node_modules') >= 0;
},
}),
new htmlWebpackPlugin({ //Generate index.html
template: './src/index.html'
}),
new webpack.ContextReplacementPlugin( //Only export the locals we need | https://github.com/moment/moment/issues/2517
/moment[\/\]locale$/, /en|nl/
)
],
resolve: {
extensions: ['.js', '.ts']
}
};
app.component.ts
import {Component} from '@angular/core';
@Component({
selector: 'hn-root',
// template: `<h1>Hello world</h1>`
templateUrl: 'app.html',
// styleUrls: ['./app.scss']
})
export class AppComponent {
}
app.html
<h1>Hello big world</h1>
package.json
{
"name": "angular-webpack-starter",
"version": "0.1.0",
"scripts": {
"build": "webpack --config webpack.dev.js",
"serve": "webpack-dev-server --config webpack.dev.js",
"build --prod": "webpack -p --config webpack.prod.js --progress"
},
"dependencies": {
"@angular/common": "4.4.4",
"@angular/compiler": "4.4.4",
"@angular/core": "4.4.4",
"@angular/forms": "4.4.4",
"@angular/http": "4.4.4",
"@angular/platform-browser": "4.4.4",
"@angular/platform-browser-dynamic": "4.4.4",
"@angular/router": "4.4.4",
"core-js": "2.5.1",
"reflect-metadata": "0.1.10",
"rxjs": "5.4.3",
"zone.js": "0.8.18"
},
"devDependencies": {
"@angular/compiler-cli": "4.4.4",
"@ngtools/webpack": "1.7.2",
"@types/core-js": "0.9.43",
"@types/node": "8.0.31",
"angular2-template-loader": "0.6.2",
"awesome-typescript-loader": "3.2.3",
"codelyzer": "3.2.0",
"html-loader": "0.5.1",
"html-webpack-plugin": "2.30.1",
"tslint": "5.7.0",
"typescript": "2.5.3",
"webpack": "3.6.0",
"webpack-bundle-analyzer": "2.9.0",
"webpack-dev-server": "2.9.1",
"webpack-merge": "4.1.0"
}
}
我显然做错了什么,但我不知道那是什么..
我试过了
正在将
templateUrl
更改为 './app.html'将
app.html
更改为app.component.html
(angular 约定)正在将
loaders:[angular2-template-loader]
更改为loaders:[angular2-template-loader?keepUrl=true]
我还检查了大多数 angular 初学者(包括 angular-cli)的 webpack.config.js,他们使用 raw-loader
而不是 html-loader
。让我想知道,html-loader
是否可以与 AOT compilation
结合使用,因为它会创建内联 html?
为了回答我自己的问题,我在 webpack.common.js 中犯了一个错误。我在应该使用密钥 rules
.
loaders
因此新代码将是:
module.exports = {
entry: {
app: './src/main.ts',
vendor: getVendorPackages()
},
output: {
path: __dirname + '/dist',
filename: "website.bundle.js"
},
module: {
rules: [
{
test: /\.html$/,
loader: 'html-loader'
}
]
},
plugins: [
new webpack.ContextReplacementPlugin( //Resolve Angular warnings
/angular(\|\/)core(\|\/)@angular/,
path.resolve(__dirname, '../src')
),
new webpack.optimize.CommonsChunkPlugin({ //Create secondary bundle containing dependencies
name: 'vendor',
filename: 'vendor.bundle.js',
minChunks(module) {
const context = module.context;
return context && context.indexOf('node_modules') >= 0;
},
}),
new htmlWebpackPlugin({ //Generate index.html
template: './src/index.html'
}),
new webpack.ContextReplacementPlugin( //Only export the locals we need | https://github.com/moment/moment/issues/2517
/moment[\/\]locale$/, /en|nl/
)
],
resolve: {
extensions: ['.js', '.ts']
}
};
或更具体:
module: {
rules: [
{
test: /\.html$/,
loader: 'html-loader'
}
]
},
您可能还会注意到 /\.ts$/
规则已消失。这是因为 AOT 编译使用它自己的 typescript 编译器并且 webpack-merge
不会覆盖规则。因此,我不得不将编译向下移动到开发配置:
webpack.dev.ts
module.exports = merge(common, {
module: {
rules: [
{
test: /\.ts$/, //Prod uses AOT for .ts and webpack does not override the rules, so they need to be separated
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
]
},
plugins: [
new BundleAnalyzerPlugin({ //Make bundle sizes visible
analyzerMode: 'static',
openAnalyzer: false
}),
new webpack.DefinePlugin({ //Set the node env so that the project knows what to enable or disable
'process.env': {
'NODE_ENV': JSON.stringify('development')
}
})
],
devtool: 'eval-source-map',
});
为了扩展我的答案并制作一个工作示例(使用 AOT 编译),我还必须向我的 tsconfig.json
添加一些数据(参见 AOT documentation):
"files": [
"src/app/app.module.ts",
"src/main.ts"
],
"angularCompilerOptions": {
"genDir": "aot",
"skipMetadataEmit" : true
}
合并后得到以下 tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"module": "es2015",
"moduleResolution": "node",
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"removeComments": false,
"sourceMap": true,
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
]
},
"files": [
"src/app/app.module.ts",
"src/main.ts"
],
"angularCompilerOptions": {
"genDir": "aot",
"skipMetadataEmit" : true
}
}