ExtractTextPlugin 不适用于 Angular AOT 构建
ExtractTextPlugin doesn't work with Angular AOT build
所以我正在尝试创建一个带有 AOT 构建的 Angular (4.4.4
) Webpack (3.6.0
) 启动器,我正在 运行 遇到提取问题css 到一个单独的包中(使用 extract-text-webpack-plugin 3.0.1
)。
当我 运行 我的产品构建时,webpack 构建卡在了 95% emitting
。它永远不会达到 100%,也永远不会输出 dist 包。起初,我尝试使用 style-loader
(0.19.0
) 创建内联 CSS,但这并不成功,因为 Angular AOT 构建没有 window 对象在构建期间(sass-loader 将在这一点上失败)。由于这个原因,我不得不在生产过程中将 css 提取到一个单独的包中(一点也不坏)。
但不知何故,编译器停止了并且从不给出错误。
webpack.common.js
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', '.scss']
}
};
Webpack.prod.js
module.exports = merge(common, {
module: {
rules: [
{
test: /\.ts$/,
loaders: ['@ngtools/webpack']
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({ // Fallback is not necessary, since style-loader will fail with AOT build
use: ["css-loader", "sass-loader"]
})
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({ // Uglyfy the JavaScript output
beautify: false,
mangle: {
screw_ie8: true,
keep_fnames: true
},
compress: {
warnings: false,
screw_ie8: true
},
comments: false
}),
new AotPlugin({ // Create AOT build
tsConfigPath: './tsconfig.json',
entryModule: __dirname + '/src/app/app.module#AppModule'
}),
new webpack.DefinePlugin({ // Set the node env so that the project knows what to enable or disable
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new ExtractTextPlugin("styles.css") //Create an external style bundle
]
});
对于产品构建,我运行正在执行以下 npm 任务:"build --prod": "webpack -p --config webpack.prod.js --progress"
我的 package.json 依赖项 看起来像这样:
"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",
"css-loader": "0.28.7",
"extract-text-webpack-plugin": "3.0.1",
"html-loader": "0.5.1",
"html-webpack-plugin": "2.30.1",
"node-sass": "4.5.3",
"sass-loader": "6.0.6",
"style-loader": "0.19.0",
"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"
}
我的Angular组件如下:
@Component({
selector: 'hn-root',
templateUrl: './app.html',
styleUrls: ['./app.scss'],
})
export class AppComponent {
}
而我的项目结构是:
- src
-- app
-- app.component.ts
-- app.html
-- app.module.ts
-- app.scss
index.html
main.ts
有人知道我做错了什么吗?
在 Angular 中阅读了更多关于视图封装的内容后,我现在知道您不应该将 style-loader 与 Angular 一起使用。
如果您想要全局样式,Style-loader
很好,但是当您希望样式仅应用于包含它们的组件时,您应该改用 raw-loader
。
所以在添加原始加载器 (npm install --save-dev raw-loader
) 之后,我将 webpack.prod.js 更改为:
module.exports = merge(common, {
module: {
rules: [
{
test: /\.ts$/,
loaders: ['@ngtools/webpack']
},
{
test: /\.scss$/,
exclude: /node_modules/,
loaders: ['raw-loader', 'sass-loader']
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({ // Uglyfy the JavaScript output
beautify: false,
mangle: {
screw_ie8: true,
keep_fnames: true
},
compress: {
warnings: false,
screw_ie8: true
},
comments: false
}),
new AotPlugin({ // Create AOT build
tsConfigPath: './tsconfig.json',
entryModule: __dirname + '/src/app/app.module#AppModule'
}),
new webpack.DefinePlugin({ // Set the node env so that the project knows what to enable or disable
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
})
]
});
这样我就可以像 Angular 推荐的那样使用视图封装(这也是 angular-cli 的做法)。
来源:
所以我正在尝试创建一个带有 AOT 构建的 Angular (4.4.4
) Webpack (3.6.0
) 启动器,我正在 运行 遇到提取问题css 到一个单独的包中(使用 extract-text-webpack-plugin 3.0.1
)。
当我 运行 我的产品构建时,webpack 构建卡在了 95% emitting
。它永远不会达到 100%,也永远不会输出 dist 包。起初,我尝试使用 style-loader
(0.19.0
) 创建内联 CSS,但这并不成功,因为 Angular AOT 构建没有 window 对象在构建期间(sass-loader 将在这一点上失败)。由于这个原因,我不得不在生产过程中将 css 提取到一个单独的包中(一点也不坏)。
但不知何故,编译器停止了并且从不给出错误。
webpack.common.js
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', '.scss']
}
};
Webpack.prod.js
module.exports = merge(common, {
module: {
rules: [
{
test: /\.ts$/,
loaders: ['@ngtools/webpack']
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({ // Fallback is not necessary, since style-loader will fail with AOT build
use: ["css-loader", "sass-loader"]
})
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({ // Uglyfy the JavaScript output
beautify: false,
mangle: {
screw_ie8: true,
keep_fnames: true
},
compress: {
warnings: false,
screw_ie8: true
},
comments: false
}),
new AotPlugin({ // Create AOT build
tsConfigPath: './tsconfig.json',
entryModule: __dirname + '/src/app/app.module#AppModule'
}),
new webpack.DefinePlugin({ // Set the node env so that the project knows what to enable or disable
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new ExtractTextPlugin("styles.css") //Create an external style bundle
]
});
对于产品构建,我运行正在执行以下 npm 任务:"build --prod": "webpack -p --config webpack.prod.js --progress"
我的 package.json 依赖项 看起来像这样:
"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",
"css-loader": "0.28.7",
"extract-text-webpack-plugin": "3.0.1",
"html-loader": "0.5.1",
"html-webpack-plugin": "2.30.1",
"node-sass": "4.5.3",
"sass-loader": "6.0.6",
"style-loader": "0.19.0",
"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"
}
我的Angular组件如下:
@Component({
selector: 'hn-root',
templateUrl: './app.html',
styleUrls: ['./app.scss'],
})
export class AppComponent {
}
而我的项目结构是:
- src
-- app
-- app.component.ts
-- app.html
-- app.module.ts
-- app.scss
index.html
main.ts
有人知道我做错了什么吗?
在 Angular 中阅读了更多关于视图封装的内容后,我现在知道您不应该将 style-loader 与 Angular 一起使用。
如果您想要全局样式,Style-loader
很好,但是当您希望样式仅应用于包含它们的组件时,您应该改用 raw-loader
。
所以在添加原始加载器 (npm install --save-dev raw-loader
) 之后,我将 webpack.prod.js 更改为:
module.exports = merge(common, {
module: {
rules: [
{
test: /\.ts$/,
loaders: ['@ngtools/webpack']
},
{
test: /\.scss$/,
exclude: /node_modules/,
loaders: ['raw-loader', 'sass-loader']
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({ // Uglyfy the JavaScript output
beautify: false,
mangle: {
screw_ie8: true,
keep_fnames: true
},
compress: {
warnings: false,
screw_ie8: true
},
comments: false
}),
new AotPlugin({ // Create AOT build
tsConfigPath: './tsconfig.json',
entryModule: __dirname + '/src/app/app.module#AppModule'
}),
new webpack.DefinePlugin({ // Set the node env so that the project knows what to enable or disable
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
})
]
});
这样我就可以像 Angular 推荐的那样使用视图封装(这也是 angular-cli 的做法)。
来源: