webentwicklung-frage-antwort-db.com.de

hotPack-Austausch des Webpacks: CSS ohne Aktualisierung

Bisher habe ich Livereload verwendet, so dass immer, wenn ich JS oder Vorlagen ändere, die Seite aktualisiert wird und wenn ich CSS ändere, das neue CSS ohne Aktualisierung aktualisiert würde.

Ich probiere jetzt Webpack aus und habe fast dasselbe Verhalten mit einer Ausnahme: Wenn sich das CSS ändert, wird das gesamte Fenster aktualisiert. Ist es möglich, das CSS ohne Aktualisierung zu wechseln?

Config soweit:

var webpackConfig = {
    entry: ["webpack/hot/dev-server", __dirname + '/app/scripts/app.js'],
    debug: true,
    output: {
        path: __dirname + '/app',
        filename: 'scripts/build.js'
    },
    devtool: 'source-map',
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new htmlWebpackPlugin({
            template: __dirname + '/app/index.html',
            inject: 'body',
            hash: true,
            config: config
        }),
        new webpack.ProvidePlugin({
            'angular': 'angular'
        }),
        new ExtractTextPlugin("styles.css")
    ],
    module: {
        loaders: [
            {
                test: /\.scss$/,
                loader: "style!css!sass?includePaths[]=" + __dirname + "/app/bower_components/compass-mixins/lib&includePaths[]=" + __dirname + '/instance/sth/styles&includePaths[]=' + __dirname + '/app/scripts'
            }
        ]
    }
};
17

Dies ist einer der Nachteile der Verwendung von ExtractTextPlugin, wie in dem Projekt README angegeben. Sie können das Problem beheben, indem Sie Ihre Konfiguration aufteilen. Ie. haben eine separate Konfiguration für die Entwicklung ohne und eine für die Produktion damit.

17

Es ist jetzt möglich, angle2, Webpack mit Hot-Module-Austausch, Sass-Quellcaps und extern geladenen CSS zu verwenden. Ich habe Tage gebraucht, damit zu spielen, aber ich habe es zum Laufen gebracht!

Die Abhängigkeiten lauten style-loader, css-loader und sass-loader (bei Verwendung von sass kann der sass loader entfernt werden.)

Ich verwende ExtractTextPlugin für den Produktionsmodus, um aktuelle .css-Dateien auszugeben.

ANMERKUNG: Damit dies funktioniert, verwende ich nicht die stylesUrl -Eigenschaft. Stattdessen importiere ich die SCS-Datei außerhalb des @Component-Dekorators, sodass die Stile im globalen Kontext geladen werden und nicht nach Komponenten.

Diese Konfiguration ermöglicht das Ersetzen von Hot Module mit SCSS-Dateien unter Verwendung des Webpack-Dev-Servers und das Extrahieren von textplugin für den Produktionsmodus, um tatsächliche .css-Dateien auszugeben.

Hier ist meine funktionierende Konfig

{
        test: /\.(scss)$/,
        use:
          isDevServer ? [
              {
                loader: 'style-loader',
              },             
              {
                loader: 'css-loader',
                options: { sourceMap: true }
              },
              {
                loader: 'postcss-loader',
                options: { postcss: [AutoPrefixer(autoPrefixerOptions)], sourceMap: true }
              },
              {
                loader: 'sass-loader',
                options: { sourceMap: true }
              },
              {
                loader: 'sass-resources-loader',
                options: {
                  resources: [
                    './src/assets/styles/variables.scss',
                    './src/assets/styles/mixins.scss']
                }
              }, 
              /**
               * The sass-vars-loader will convert the 'vars' property or any module.exports of 
               * a .JS or .JSON file into valid SASS and append to the beginning of each 
               * .scss file loaded.
               *
               * See: https://github.com/epegzz/sass-vars-loader
               */
              {
                loader: '@epegzz/sass-vars-loader?',
                options: querystring.stringify({
                  vars: JSON.stringify({
                    susyIsDevServer: susyIsDevServer
                  })
                })
              }] : // dev mode
          ExtractTextPlugin.extract({
            fallback: "css-loader",
            use: [
              {
                loader: 'css-loader',
                options: { sourceMap: true }
              },
              {
                loader: 'postcss-loader',
                options: { postcss: [AutoPrefixer(autoPrefixerOptions)], sourceMap: true }
              },
              {
                loader: 'sass-loader',
                options: { sourceMap: true }
              },
              {
                loader: 'sass-resources-loader',
                options: {
                  resources: [
                    './src/assets/styles/variables.scss',
                    './src/assets/styles/mixins.scss']
                }
              }, {
                loader: '@epegzz/sass-vars-loader?',
                options: querystring.stringify({
                  vars: JSON.stringify({
                    susyIsDevServer: susyIsDevServer
                  })
                  // // Or use 'files" object to specify vars in an external .js or .json file
                  // files: [
                  //    path.resolve(helpers.paths.appRoot + '/assets/styles/sass-js-variables.js')
                  // ],
                })
              }],
            publicPath: '/' // 'string' override the publicPath setting for this loader
          })
      },

Dann würden Sie in Ihrer Komponente beispielsweise app.component.ts Ihre app.style.scss-Datei OUTSIDE des @Component-Dekorators benötigen.

Das ist der Trick. Dies funktioniert nicht, wenn Sie Stile mit "stylesUrl" auf "winkelige Weise" laden. Wenn Sie dies auf diese Weise tun, können Sie .css-Stylesheets für Komponenten laden, die nur langsam geladen werden, was die anfängliche Ladezeit noch beschleunigt.

app.component.css

/*
 * THIS IS WHERE WE REQUIRE CSS/SCSS FILES THAT THIS COMPONENT NEEDS
 *
 * Function: To enable so-called "Lazy Loading" CSS/SCSS files "on demand" as the app views need them.
 * Do NOT add styles the "Angular2 Way" in the @Component decorator ("styles" and "styleUrls" properties)
 */
    import './app.style.scss'

/**
 * AppComponent Component
 * Top Level Component
 */
@Component({
   selector: 'body',
   encapsulation: ViewEncapsulation.None,
   Host: { '[class.authenticated]': 'appState.state.isAuthenticated' },
   templateUrl: './app.template.html'
})

Ich habe keine Probleme gehabt, dieses Setup auszuführen. Bitte schön!

sass_sourcemaps _hmr _wds

Stand 08/2017: Verbesserte Konfiguration für Webpack 3+ Schema-Anforderungen und Verwendung von Angular 4 AOT-Kompilierung.

4
TetraDev

Es gibt tatsächlich einen einfachen Weg, dies zu tun. Ich verwende sass-loader mit extract-text-plugin, das CSS-Dateien erzeugt.

Was Sie tun müssen, ist eine ID zu Ihrem CSS-Include hinzuzufügen

  <link id="js-style" type="text/css" rel="stylesheet" href="/static/main.css">

Jetzt müssen Sie sicherstellen, dass bei einem HMR die aktuelle Version/Zeitmarke aktualisiert wird. Sie können dies auf folgende Weise tun:

import '../style/main.scss'
if (module.hot) {
  module.hot.accept('../style/main.scss', () => {
    const baseStyle = window.document.getElementById('js-style')
    baseStyle.setAttribute('href', '/static/main.css?v=' + new Date().valueOf)
  })
}

Wenn sich css ändert, werden wir die URL von css include korrigieren, um es neu zu laden.

2
Hatch

Obwohl ExtractTextPlugin in seinem Abschnitt README "No Hot Module Replacement" (Kein Hot Module Replacement) angibt , habe ich dies behoben, indem die CSS-Dateien manuell über die BrowserSync-API aktualisiert wurden.

Ich habe gaze verwendet, um auf Änderungen in meinen CSS-Dateien zu achten, und BrowserSync dann zum Aktualisieren verwendet.

    npm install gaze

Sie können dies auch ganz einfach tun, indem Sie Ihr Build-Skript mit den folgenden Elementen bearbeiten:

  const { Gaze } = require('gaze');

  // Your own BrowserSync init
  browserSync.init({
    ...
  }, resolve);

  // Create a watcher:
  // You can watch/reload specific files according to your build/project structure
  const gaze = new Gaze('**/*.css');
  gaze.on('all', () => bs.reload('*.css'));

Hoffentlich hilft das.

1
urip

Sie können 'css-hot-loader' verwenden, um HMR für Ihre extrahierte css zu aktivieren. Es funktioniert perfekt für mich.

0
ddemakov