2015-06-14 12 views
17

Finora ho utilizzato il livereload in modo tale che ogni volta che cambio JS o modelli, la pagina si aggiorna e quando cambio CSS, eseguirà automaticamente il nuovo CSS senza aggiornare.sostituzione del modulo hot di webpack: css senza aggiornamento

Sto provando il webpack ora e ho quasi raggiunto lo stesso comportamento, con un'eccezione: quando il CSS cambia, aggiorna l'intera finestra. È possibile renderlo hotswap nel CSS senza aggiornare?

Config finora:

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

risposta

16

Questo è uno degli aspetti negativi di utilizzare ExtractTextPlugin come indicato in the project README. È possibile risolvere il problema suddividendo la configurazione. Vale a dire. avere una configurazione separata per lo sviluppo senza di essa e una per la produzione con esso.

+1

Ho creato https://github.com/sheerun/extracted-loader per risolvere questo problema – sheerun

4

Ora è possibile utilizzare angular2, webpack con sostituzione di moduli caldi, sass sourcemaps e css caricati esternamente. Mi ci sono voluti giorni di gioco ma ho funzionato!

Le dipendenze sono style-loader, css-loader e sass-loader (se si utilizza sass, se non, il caricatore sass può essere rimossa)

posso utilizzare ExtractTextPlugin per modalità di produzione ad emettere .css effettivi.

NOTA: per far funzionare tutto questo, non uso la proprietà stylesUrl, ma imposto il file .scss al di fuori del decoratore @Component in modo che gli stili vengano caricati nel contesto globale, piuttosto che in base al componente.

Questa configurazione consente la sostituzione del modulo caldo con i file SCSS utilizzando il server di sviluppo Webpack e il plug-in estrai per la modalità di produzione per l'emissione di file .css effettivi.

Ecco la mia configurazione di lavoro

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

Poi, nel componente, ad esempio, app.component.ts, si richiederebbe il tuo app.style.scss file di al di fuori della @Component decoratrice.

Questo è il trucco. Questo non funzionerà se carichi stili "angolare" con stylesUrl. Facendolo in questo modo potrai caricare pigro i fogli di stile .css per i componenti che sono pigri, rendendo il tempo di caricamento iniziale ancora più veloce.

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

ho avuto problemi in esecuzione questa configurazione. Ecco qui!

sass_sourcemaps _hmr _wds

Aggiornato 08/2017: Migliorata la configurazione per webpack 3+ requisiti dello schema, e di lavorare con angolare 4 compilazione AOT.

+0

Grazie per la vostra ampia risposta. Ho ancora bisogno di provarlo, il che potrebbe richiedere un po 'di tempo perché abbiamo parcheggiato il progetto del webpack per un po', ma la tua risposta sembra promettente! –

1

Sebbene in ExtractTextPlugin sia indicato "Nessuna sostituzione di moduli caldi" nel suo README section, , l'ho risolto aggiornando manualmente i file CSS tramite l'API BrowserSync.

Ho utilizzato gaze per ascoltare eventuali modifiche nei miei file CSS e quindi utilizzato BrowserSync per aggiornarli.

npm install gaze 

Si può anche facilmente farlo modificando il tuo script di build con qualcosa di quanto segue:

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')); 

Speranza che aiuta.

2

C'è in realtà un modo semplice per farlo. Sto usando sass-loader con estra-text-plugin che produce file CSS.

Quello che dovete fare è aggiungere al vostro id CSS includono

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

Ora, è necessario assicurarsi quando HMR accade si aggiorna URL con l'attuale versione/timestamp. È possibile farlo in modo tale:

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

Così ogni volta che cambia css, ti fissare URL del css includono ricaricarlo.

Problemi correlati