2016-10-06 37 views
5

我正在使用html-webpack-plugin插件将<script>标签注入到webpack生成的块的模板文件中。我还有一些全球样式表,我想动态添加到我的HTML模板的<head>部分。为此,我也使用html-webpack-plugin(如下所示)(在这种情况下,app entry/chunk是相关的)。在Webpack中忽略Angular2组件样式表ExtractTextPlugin

module.exports = { 
    entry: { 
     'polyfills': './ts/polyfills.ts', 
     'vendor': './ts/vendor.ts', 
     'app': './ts/app.ts' 
    }, 

    module: { 
     loaders: [ 
      { 
       test: /\.ts$/, 
       loaders: ['ts', 'angular2-template-loader'] 
      }, 
      { 
       test: /\.html$/, 
       loader: 'html-loader' 
      }, 
      { 
       test: /\.css$/, 
       loaders: ['to-string-loader', ExtractTextPlugin.extract('style-loader', 'css-loader')] 
      } 
     ] 
    }, 

    plugins: [ 
     new ExtractTextPlugin('css/[name].[contenthash].css'), 

     new webpack.ProvidePlugin({ 
      bootstrap: 'bootstrap' 
     }), 

     new webpack.optimize.CommonsChunkPlugin({ 
      name: 'app', 
      filename: 'js/[name].[chunkhash].min.js', 
      chunks: ['app'] 
     }), 

     new webpack.optimize.CommonsChunkPlugin({ 
      name: 'vendor', 
      filename: 'js/[name].[chunkhash].min.js', 
      chunks: ['vendor'] 
     }), 

     new webpack.optimize.CommonsChunkPlugin({ 
      name: 'polyfills', 
      filename: 'js/[name].[chunkhash].min.js', 
      chunks: ['polyfills'] 
     }), 

     new HtmlWebpackPlugin({ 
      template: 'my-template.html', 
      filename: 'my-template.html', 
      inject: 'body', 
      hash: false 
     }), 
    ] 
}; 

下面是app.ts文件,在那里我已经添加了每一个我想在我的模板中包含的样式表(它们被合并在一起,成为一个样式表)一个require声明。

require('main.css'); 
require('misc.css'); 

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 
import { AppModule } from './app.module'; 

platformBrowserDynamic().bootstrapModule(AppModule); 

本质上讲,这工作得很好,但前提条件是,我使用此配置用于Angular2应用,它是由可具有相关联的样式表,像在本例中的组件。

@Component({ 
    styleUrls: [ 
     'my-stylesheet.css' 
    ] 
}) 
export class MyComponent { ... } 

构建应用程序通常会导致一吨,这些样式表的成分HTTP调用,所以要解决这个问题,我已经用angular2-template-loader直接拉进样式表的组件。该装载机的工作如下。

的angular2模板装载机搜索templateUrl和styleUrls的角2组分元数据的内部 声明和替换与相应需要声明 的路径。

这样做的问题是,除了被添加到app.ts入口点两个样式表的WebPack还包括每一个从我Angular2部件引用样式表。因为它经历了应用程序的依赖关系,并且找到了由angular2-template-loader添加的require语句。这是不可取的,因为我希望这些样式表对于它们所属的组件是本地的,即在JS中内联。

因此,我需要一种方法来只有包括样式表,我require直接在我的入口点,也许以某种方式排除组件样式表。问题是,在这两种情况下,该文件都具有.css扩展名,所以它们都通过了extract-text-plugin的测试。我看了看加载程序/插件的文档,但找不到任何能解决我的问题的东西。

所以,我要的是一个app.[contenthash].css文件添加到我的模板文件(这部分作品),但不包括我Angular2组件引用的样式表(包括在内,因为angular2模板型装载机)。

如何防止将这些Angular2组件样式表包含在添加到我的HTML模板中的样式表中?

回答

5

比方说,你有以下文件夹结构:

enter image description here

所以我所有的组件都位于内应用文件夹。

main.ts

require('main.css'); 
require('misc.css'); 

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 
import { AppModule } from './app.module'; 

platformBrowserDynamic().bootstrapModule(AppModule); 

/app/app.component.ts

@Component({ 
    selector: 'my-app', 
    template: `<h1>My Angular 2 App</h1>`, 
    styleUrls: ['my-stylesheet.css'] 
}) 
export class AppComponent {} 

那么您的解决方案可能是:

webpack.config.js

{ 
    test: /\.css$/, 
    exclude: /app\\.+\.css$/, <== add this (exclude all styles from app folder) 
    loaders: ['to-string-loader', ExtractTextPlugin.extract('style-loader', 'css-loader')] 
}, 
{ 
    test: /app\\.+\.css$/, 
    loader: 'raw' <== use raw loader for these files 
} 
+0

啊,这看起来不错!我会尽快让它旋转,让你知道它是如何发生的。谢谢! – Andy0708

+0

我尝试过玩这个游戏,但无法启动它。首先,我的CSS文件位于'public/css',其中组件的样式表位于'public/css/components/**/*。css'。我试图在第一个加载器中排除'/ public \/css \/components /',并在第二个加载器中使用'raw',并且使用了许多不同的测试和排除以及各种不同的错误。我不知道我是否搞乱了路径/正则表达式或问题是什么。如果你能提供一个前面提到的路径的例子,那真的很棒,因为我似乎无法让它起作用。 – Andy0708

+0

尝试使用'/ public \\ css \\ components /'或'/ css \\ components /' – yurzui

1

您可以通过使用两个独立的名称模式给webpack一个提示来区分CSS文件。假设您命名了带有后缀.tl(模板加载程序的简写,例如mycss.tl.css)以及带有后缀.pt(平台的缩写,例如,平台)的angular2-template-loader应包含的所有文件。main.pt.css),那么你可以写出如下的WebPack配置:

module: { 
     loaders: [ 
      { 
       test: /\.ts$/, 
       loaders: ['ts', 'angular2-template-loader'] 
      }, 
      { 
       test: /\.pt\.css$/, 
       loaders: ['to-string-loader', ExtractTextPlugin.extract('style-loader', 'css-loader')] 
      }, 
      { 
       test: /\.tl\.css$/, 
       loaders: ['style-loader', 'css-loader'] 
      } 
     ] 
    } 

你的组件定义则看起来像

@Component({ 
    styleUrls: [ 
     'my-stylesheet.tl.css' 
    ] 
}) 
export class MyComponent { ... } 

而在app.ts放置

require('main.pt.css'); 
require('misc.pt.css'); 

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 
import { AppModule } from './app.module'; 

platformBrowserDynamic().bootstrapModule(AppModule); 

angular2模板装载机然后仍然使用require来调用css路径,但根据您的配置,您可以为css文件设置不同的加载器集。

+0

我实际上正在考虑做类似的事情,但在我看来这似乎是一种破解,所以我想知道是否有更好的解决方案。我会玩一下,看看我能想出什么。谢谢您的回答! :-) – Andy0708

0

对于任何有兴趣的人,我确实设法解决这个问题,灵感来自@ yurzui的答案。

module: { 
    loaders: [ 
     { 
      test: /\.ts$/, 
      loaders: ['ts', 'angular2-template-loader'] 
     }, 
     { 
      test: /\.css$/, 
      exclude: [helpers.root('public', 'css', 'components')], 
      loaders: ['to-string-loader', ExtractTextPlugin.extract('style-loader', 'css-loader')] 
     }, 
     { 
      test: /\.css$/, 
      include: [helpers.root('public', 'css', 'components')], 
      loaders: ['raw-loader'] 
     } 
    ] 
} 

在上面的示例中,我使用我的自定义帮助程序来组装路径到目录。你可以通过其他方式做到这一点,但无论如何,这里是我的帮手(取自Angular2的文档)。

var path = require('path'); 
var _root = path.resolve(__dirname, '..'); // This file is stored within a webpack subdirectory in my case 

function root(args) { 
    args = Array.prototype.slice.call(arguments, 0); 
    return path.join.apply(path, [_root].concat(args)); 
} 

exports.root = root; 

要使用它,只需要在您的webpack配置中使用它。

var helpers = require('./helpers'); 

我希望这有助于某人。