2016-07-14 330 views
6

Sto cercando di rendere l'app React modificabile. Per ora i temi consistono solo di diversi insiemi di variabili sass che definiscono diversi colori di intestazione, ecc.Come estrarre più fogli di stile del tema con il webpack?

Dal mio punto di vista attuale lo ExtractTextPlugin sembra essere la mia migliore scommessa in quanto non voglio che i miei stili siano in linea e piuttosto separati file per tema.

Così ho creato due temi:

src/scss/themes/theme-a.scss 
src/scss/themes/theme-b.scss 

I temi importare il layout di base e gli stili comuni e sovrascrivere le variabili rilevanti.

Ma l'unico modo sono riuscito a fare webpack creare file css separati per entrambi i temi è stato quello di creare punti di ingresso distinti per ogni tema in mia webpack.prod.config:

entry: { 
    app: './src/js/init.js', 
    theme-a: './src/scss/themes/theme-a.scss', 
    theme-b: './src/scss/themes/theme-b.scss' 
}, 

Ma l'aggiunta di un nuovo punto di ingresso per ogni il nuovo tema che viene aggiunto si sente sbagliato e immagino ci debba essere un modo migliore?

+0

Hm, credo che hai bisogno di un punto di riferimento in 'plugins', simile a' nuova ExtractTextPlugin ('css/bundle.css') '. Non ho visto gente che metta queste "voci" di introduzione. Separo solo i CSS in un singolo file, ma controlla qui, sembra estrarre 2 file nell'esempio (sia esso css e meno): https://github.com/webpack/extract-text-webpack-plugin#api – lux

+0

Hm, ma l'aggiunta di più istanze di plugin invece di più voci non sembra molto più comoda. Cosa sarebbe bello se si potesse dire al plugin che sputa un file css separato per ogni file scss che incontra all'interno di una certa fonte/cartella. – arie

risposta

7

, ecco la soluzione:

npm i --save-dev file-loader 

Nella sezione loaders, aggiungere questo:

{ 
    test: /themes\/.+\.scss$/, 
    loader: "file-loader?name=./compiled-themes/css/[name].css!css!sass" 
}, 

Ci possono essere più file SCSS, in tal caso ci deve essere un'altra sezione che li impacchetta come al solito, ma salta i temi:

{ 
    test: /\.scss$/, 
    exclude: /themes\/.+\.scss$/, 
    loader: "css!sass" 
}, 

Il caricatore di file scrive file per nomefile, hash a estensione nd in modo da poter conservare il nome.

Nota la parte name=./compiled-themes/css/[name].css, in cui le voci [] sono sostituite.

https://github.com/webpack/file-loader

+0

per chiarire, il caricatore di file è in realtà un autore di file, ma ha questo suffisso -loader secondo la convenzione di denominazione del plugin webpack –

+1

Questa sembra una soluzione davvero bella! Ho provato ad adattare il tuo esempio e vengono creati i temi compilati. Grande! Ma in qualche modo i file non sono costituiti da puro css ma sono racchiusi in un modulo 'exports = module.exports = require (" ./../../../ node_modules/css-loader/lib/css-base.js ")();' '// importazioni' ' // module' 'exports.push ([module.id," .ReactModal__Overlay {z-index: 999; overflow: auto; margine: 0! Important; padding: 0 ... ' Hai un'idea di quale potrebbe essere il problema? La mia riga di caricamento per i temi è simile a questa: ' loader: "file-loader? Name =./Compiled -themes/css/[name] .css! css! sass "' – arie

+0

'raw! saas' farebbe il trucco. Ho appena provato. Devi' npm i raw-loader' –

2

Per evitare di dover aggiungere manualmente i temi, una possibile soluzione consiste nel creare una funzione che legge i contenuti della cartella temi e aggiungere automaticamente una voce per ciascun file * .scss.

Qualcosa sulla falsariga di questo:

function getThemes(themePath) { 
    var themes = {}; 
    fs.readdirSync(themePath).forEach(function(fileName) { 
     var fileNameWithPath = path.join(themePath, fileName); 

     var stat = fs.lstatSync(fileNameWithPath); 
     if (stat.isDirectory()) return; 
     if (!/\.scss$/.test(fileName)) return; 

     var nameWithoutExt = path.basename(fileName, '.scss'); 
     themes[nameWithoutExt] = fileNameWithPath; 
    }); 

    return themes; 
} 

var themes = getThemes('./src/scss/themes'); 

var config= { 
    entry: _.merge({ app: './src/js/init.js' }, themes), 
    // rest of options 
}; 

Ciò richiederà il riavvio del dev-server o re-run a costruire webpack quando l'aggiunta di file nuovo tema, però, ma almeno non avrà per toccare la tua configurazione del webpack.

+0

Questa configurazione sembra comportare l'emissione di un file JS per ogni file CSS e il file CSS stesso. C'è un modo per fermare l'output del file JS? – Giuseppe