2016-10-06 5 views
5

Ich verwende das Plugin, um <script> Tags in eine Vorlagendatei für die Brocken zu injizieren, die Webpack generiert. Ich habe auch ein paar globale Stylesheets, die ich dynamisch zum <head> Abschnitt meiner HTML-Vorlage hinzufügen möchte. Dazu benutze ich auch das html-webpack-plugin wie folgt (der app entry/chunk ist in diesem Fall der relevante).Ignorieren Angular2 Komponente Stylesheets mit ExtractTextPlugin in Webpack

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 
     }), 
    ] 
}; 

Unten ist die app.ts Datei, wo ich eine require Anweisung für jede Sheet hinzugefügt haben, die Ich mag würde in meiner Vorlage aufgenommen (sie zusammen in einem einzigen Sheet zusammengefasst werden).

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

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

platformBrowserDynamic().bootstrapModule(AppModule); 

Im Wesentlichen funktioniert dies gut, aber der Haken ist, dass ich diese Konfiguration für eine Angular2 Anwendung verwenden, die aus Komponenten besteht, die Sheets zugeordnet hat, wie in diesem Beispiel.

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

die Anwendung Aufbau normalerweise in einer Tonne von HTTP-Aufrufe für diese Sheets für die Komponenten führen würde, so dass diese zu lösen, habe ich durch die Verwendung angular2-template-loader die Stylesheets direkt in die Komponenten gezogen. Dieser Lader funktioniert wie folgt.

Der angular2-template-Lader sucht nach templateUrl und styleUrls Erklärungen innerhalb der Angular 2 Komponenten-Metadaten und ersetzt die Pfade mit der erfordern Anweisung entspricht.

Das Problem dabei ist, dass neben den beiden Stylesheets, die den app.ts Einstiegspunkt hinzugefügt werden, webpack umfasst auch jedes Sheet, das von meinen Angular2 Komponenten verwiesen wird. Weil es die Abhängigkeiten der Anwendung durchläuft und die von angular2-template-loader hinzugefügten require-Anweisungen findet. Dies ist unerwünscht, weil ich möchte, dass diese Stylesheets lokal zu den Komponenten sind, zu denen sie gehören, d. H. In JS inline sind.

Deshalb brauche ich einen Weg zu nur umfasst die Stylesheets, die ich require direkt in meinen Einstiegspunkten, vielleicht irgendwie die Komponente Sheets auszuschließen. Das Problem ist, dass in beiden Fällen die Datei die Erweiterung .css hat, so dass beide den Test für die extract-text-plugin bestehen. Ich habe mir die Dokumentation der Loader/Plugins angeschaut, aber ich konnte nichts finden, was mein Problem lösen würde.

Also, was ich will, ist eine app.[contenthash].css Datei zu meiner Vorlagendatei (Dieser Teil funktioniert) hinzufügen, aber ohne die referenzierten Stylesheets in meiner Angular2 Komponente (inklusive wegen angular2-template-Lader).

Wie kann ich verhindern, dass diese Stylesheets für Angular2-Komponenten in das Stylesheet eingefügt werden, das meiner HTML-Vorlage hinzugefügt wird?

Antwort

5

Angenommen, Sie haben die folgende Ordnerstruktur haben:

enter image description here

So sind alle meine Komponenten innerhalb App Ordner befinden.

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 {} 

Dann könnte Ihre Lösung aussehen:

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

Ah, das sieht ziemlich gut aus! Ich werde es so schnell wie möglich drehen und Sie wissen lassen, wie es läuft. Vielen Dank! – Andy0708

+0

Ich habe versucht, damit herumzuspielen, aber ich konnte es nicht zum Laufen bringen. Zuallererst befinden sich meine CSS-Dateien unter 'public/css', wo sich die Stylesheets für die Komponenten unter' public/css/components/**/*. Css' befinden. Ich habe versucht, "/ public \/css \/components /" im ersten Loader auszuschließen und "rohe" für die zweite, zusammen mit vielen verschiedenen Tests und schließt mit verschiedenen Fehlern aus. Ich bin mir nicht sicher, ob ich mit den Pfaden/Regex herumspiele oder was das Problem ist. Wenn Sie ein Beispiel mit den oben erwähnten Pfaden geben könnten, wäre das wirklich großartig, weil ich es nicht zum Laufen bringen kann. – Andy0708

+0

Probieren Sie '/ public \\ css \\ components \' oder '/ css \\ components /' – yurzui

1

Sie könnten webpack einen Hinweis geben, um die CSS-Dateien zu unterscheiden, indem Sie zwei getrennte Namensmuster verwenden. Angenommen, Sie benennen alle Dateien, die von angular2-template-loader mit dem Suffix .tl (kurz für Vorlagenlader, z. B. mycss.tl.css) und die anderen mit Suffix .pt (kurz für Plattform, z.main.pt.css), dann können Sie die webpack Config wie folgt schreiben:

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'] 
      } 
     ] 
    } 

Ihre Komponentendefinition sieht dann aus wie

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

während in app.ts Sie

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

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

platformBrowserDynamic().bootstrapModule(AppModule); 

angular2-template-loader platzieren wickelt dann die css-Pfade immer noch mit require-Aufrufen um, aber basierend auf Ihrer Konfiguration können Sie einen anderen Satz von Ladeprogrammen für die CSS-Dateien haben.

+0

Ich dachte eigentlich daran, so etwas zu tun, aber es schien wie ein Hack in meinem Kopf, also fragte ich mich, ob es eine bessere Lösung gab. Ich werde ein bisschen herumspielen und sehen, was ich daraus machen kann. Vielen Dank für Ihre Antwort! :-) – Andy0708

0

Für alle, die interessiert sind, habe ich es geschafft, das Problem zu lösen, inspiriert von @ Yurzuis Antwort.

Im obigen Beispiel verwende ich einen benutzerdefinierten Helfer von mir, um den Pfad zu den Verzeichnissen zusammenzustellen. Du könntest das irgendwie anders machen, aber hier ist mein Helfer sowieso (aus der Dokumentation von 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; 

Um es zu verwenden, benötigen Sie es einfach in Ihrer Webpack-Konfiguration.

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

Ich hoffe, das hilft jemandem.

Verwandte Themen