npm install css-loader style-loader --save-dev
module:{ rules:[{ test:/\.css$/, use: ['style-loader', 'css-loader'], }] },
body { background: cornsilk; }
而後在index.js中引入css
import './main.css';
再運行npm start,在http://localhost:8080/中打開html
這時候頁面出現了背景色,並且發現樣式寫入了header中,這個時候你改變顏色,界面也會無刷新的更新,這正是上一節HMR的效果。webpack
樣式也是經過webpackHotUpdate方法進行更新。git
再看一下如何加載less,先安裝less-loadergithub
npm install less less-loader --save-dev
再修改配置文件:web
module:{ rules:[{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'], }] },
而後創建一個less文件。less.lessnpm
@base: #f938ab; .box-shadow(@style, @c) when (iscolor(@c)) { -webkit-box-shadow: @style @c; box-shadow: @style @c; } .box-shadow(@style, @alpha: 50%) when (isnumber(@alpha)) { .box-shadow(@style, rgba(0, 0, 0, @alpha)); } .box { color: saturate(@base, 5%); border-color: lighten(@base, 30%); div { .box-shadow(0 0 5px, 30%) } } body { background: cornsilk; }
修改index.jsapp
import './less.less'; import component from './component'; var ele=document.createElement("div"); ele.innerHTML="this is an box"; ele.className="box"; document.body.appendChild(ele); let demoComponent=component(); document.body.appendChild(demoComponent);
獲得效果:less
能夠看見編譯成功,要注意的是,再使用less的時候import只能是less文件,這個時候再import main.css會報錯。這一節對less就作一個簡單的演示,其餘樣式預處理器同理,下面的內容仍是繼續基於css。ide
通常來講css的做用域都是全局的,咱們常在母版頁裏面添加了多個樣式文件,後面的樣式文件會覆蓋前面的樣式文件,經常給咱們的調試帶來麻煩。而CSS Modules經過import引入了本地做用域。這樣可以避免命名空間衝突。webpack的css-loader是支持CSS Modules的,怎麼理解呢,先看幾個例子。咱們先在配置中開啓(先關掉HMR):
module:{ rules:[{ test:/\.css$/, use: ['style-loader', { loader: 'css-loader', options: { modules: true,//讓css-loader支持Css Modules。 }, },],
而後定義一個新的樣式(main.css):
body {
background: cornsilk;
}
.redButton {
background: red;color:yellow;
}
給component加一個樣式,先引入main.css。
import styles from './main.css'; export default function () { var element = document.createElement('h1'); element.className=styles.redButton; element.innerHTML = 'Hello webpack'; return element; }
這個時候咱們看到界面已經變化了。
再看右邊生成的樣式,咱們的樣式名稱已經發生了改變。回顧整個過程至關於main.css中的每個類名成了一個模塊,在js中能夠像獲取模塊同樣的獲取。可是你可能想,爲毛我不能直接給元素賦值,幹嗎要import呢。這是個好問題,咱們再新增一個樣式
other.css
.redButton {
background:rebeccapurple;color:snow;
}
它也有一個.redbutton的類(但效果是紫色的),而後在index.js中建立一個div元素並給它添加redbutton樣式。
import './main.css'; import styles from './other.css'; import component from './component'; var ele=document.createElement("div"); ele.innerHTML="this is an other button"; ele.className=styles.redButton; document.body.appendChild(ele); let demoComponent=component(); document.body.appendChild(demoComponent);
再看效果
上面這個圖說明了兩問題,一個是咱們在index.js中引入了2個樣式文件,在index頁面就輸出了兩個style,這讓人有點不爽,但咱們後面再解決。另一個就是雖然兩個樣式文件中都有redButton這個類,可是這二者仍是保持獨立的。這樣就避免了命名空間的相互干擾。若是你這個時候直接賦值
element.className="redButton";
這樣是獲取不到樣式的。直接對元素的樣式默認是全局的。
若是想讓某個樣式是全局的。能夠經過:global來包住。
other.css
:global(.redButton) { background:rebeccapurple;color:snow; border: 1px solid red; }
main.css
:global(.redButton) { background: red;color:yellow; }
這個時候redbutton這兩個樣式就會合並。須要直接經過樣式名來獲取。
element.className="redButton";
咱們再修改other.css,建立一個shadowButton 樣式,內部經過composes組合redbutton類。
.redButton { background:rebeccapurple;color:snow; border: 1px solid red; } .shadowButton{ composes:redButton; box-shadow: 0 0 15px black; }
修改index.js:
var ele=document.createElement("div"); ele.innerHTML="this is an shadowButton button"; console.log(styles); ele.className=styles.shadowButton; document.body.appendChild(ele);
看一下是什麼效果:
日誌打印出來的是styles對象,它包含了兩個類名。能夠看見shadowButton是由兩個類名組合而成的。div的class和下面的對應。
npm install extract-text-webpack-plugin --save-dev
先安裝extracttextplugin這個插件,而後再webpack.config.js中進行配置:
const ExtractTextPlugin = require('extract-text-webpack-plugin'); const extractTxtplugin = new ExtractTextPlugin({ filename: '[name].[contenthash:8].css', }); const commonConfig={ entry: { app: PATHS.app, }, output: { path: PATHS.build, filename: '[name].js', }, module:{ rules:[{ test:/\.css$/, use:extractTxtplugin.extract({ use:'css-loader', fallback: 'style-loader', }) }]}, plugins: [ new HtmlWebpackPlugin({ title: 'Webpack demo', }), extractTxtplugin ], }
一開始看到這個配置,讓人有點懵。首先看fileName,表示最後輸出的文件按照這個格式'[name].[contenthash:8].css',name默認是對應的文件夾名稱(這裏是app),contenthash會返回特定內容的hash值,而:8表示取前8位。固然你也能夠按照其餘的格式寫,好比直接命名:
new ExtractTextPlugin('style.css')
而ExtractTextPlugin.extract自己是一個loader。fallback:'style-loader'的意思但有css沒有被提取(外部的css)的時候就用style-loader來處理。注意到如今咱們的index.js以下:
import './main.css'; import styles from './other.css'; import component from './component'; var ele=document.createElement("div"); ele.innerHTML="this is an box"; ele.className=styles.shadowButton; document.body.appendChild(ele); let demoComponent=component(); document.body.appendChild(demoComponent); //HMR 接口 if(module.hot){ module.hot.accept('./component',()=>{ const nextComponent=component(); document.body.replaceChild(nextComponent,demoComponent); demoComponent=nextComponent; }) }
引入了兩個css文件。
這個時候咱們執行 npm run build
再看文件夾獲得一個樣式文件。(若是不想看到日誌能夠直接npm build)
可是咱們在第三部分使用了CSS Modules,發現other.css的樣式沒有打包進來。因此,咱們的webpack.config.js還要修改:
module:{ rules:[{ test:/\.css$/, use:extractTxtplugin.extract({ use:[ { loader: 'css-loader', options: { modules: true, }, }], fallback: 'style-loader', }) }]},
再次build。
發現兩個樣式打包成了一個文件。只要內容發生了變化,樣式的名稱就會變化。更多配置能夠移步https://www.npmjs.com/package/extract-text-webpack-plugin
參考:
https://www.npmjs.com/package/css-loader#local-scope
https://survivejs.com/webpack/styling/loading/