css
在html
中經常使用的引入方式有兩種,即經過<link>
和<style>
兩種標籤在html
頭部引入樣式,如今結合webpack
來實現上述功能。css
style
標籤引入樣式第一步:安裝css-loader
和style-loader
,webpack
不知道如何提取解析樣式文件,須要這些加載器來告訴它html
css-loader
:主要用於加載css
文件,並處理css
中的依賴,例如@import
和url()
等引用外部文件的聲明
參考:https://github.com/webpack-contrib/css-loadernode
style-loader
:會將css-loader
解析的結果轉變成JS
代碼,運行時動態插入style
標籤來讓CSS
代碼生效。webpack
第二步:更改配置文件git
const path = require('path') const { CleanWebpackPlugin } = require('clean-webpack-plugin') const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { entry: { main: './css-handle/app.js' }, output: { path: path.resolve(__dirname, 'build'), // 打包文件的輸出目錄 filename: '[name].bundle.js', // 代碼打包後的文件名 publicPath: './', // 引用的路徑或者 CDN 地址 chunkFilename: '[name].js' // 代碼拆分後的文件名 }, module: { rules: [{ test: /\.css$/, use: [{ loader: 'style-loader' }, { loader: 'css-loader' }] }] }, // 拆分代碼配置項 optimization: { splitChunks: { chunks: 'all', minSize: 30000, maxSize: 0, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { common: { name: 'common', minSize: 0, //表示在壓縮前的最小模塊大小,默認值是 30kb,若是沒設置爲0,common模塊就不會抽離爲公共模塊,由於原始大小小於30kb minChunks: 2, // 最小公用次數 priority: 5, // 優先級 reuseExistingChunk: true // 公共模塊必開啓 }, vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } } }, plugins: [ new CleanWebpackPlugin(), // 會刪除上次構建的文件,而後從新構建 new BundleAnalyzerPlugin(), new HtmlWebpackPlugin({ // 打包輸出HTML title: '自動生成 HTML', minify: { // 壓縮 HTML 文件 removeComments: true, // 移除 HTML 中的註釋 collapseWhitespace: true, // 刪除空白符與換行符 minifyCSS: true // 壓縮內聯 css }, filename: 'index.html', // 生成後的文件名 template: path.resolve(__dirname, 'index.html'), // 根據此模版生成 HTML 文件 chunks: ['main'] // entry中的 main 入口才會被打包 }) ] }
注意:module.rules.use 數組中,loader 的位置。根據 webpack 規則:放在最後的 loader 首先被執行,從上往下寫的話是下面先執行,從左往右寫的話是右邊先執行。
這裏css-loader應該先於style-loader執行,先加載css文件而後再樣式插入到DOM中。
第三步:打包測試github
// a.js console.log('A') export default 'A' // app.js import '../assets/css/base.css' import(/* webpackChunkName: 'a'*/ './a').then((a) => { console.log(a) })
運行cnpm run dev
打包入口文件app.js
web
當base.css
文件中還引入其餘樣式文件,咱們也來打包看看npm
// style.css html { font-size: 16px; } // base.css @import './style.css'; *, body { margin: 0; padding: 0; } html { background-color: red; } // app.js import '../assets/css/base.css' import(/* webpackChunkName: 'a'*/ './a').then((a) => { console.log(a) })
能夠看到每個樣式文件都對應着一個style
標籤數組
咱們能夠看到生成的html
文件中並無引入樣式文件代碼,可是瀏覽器打開index.html
文件時是有引入樣式的,這是爲何呢?瀏覽器
這是由於樣式文件base.css
和入口文件app.js
將會一塊兒被打包到main.bundle.js
文件裏面,當瀏覽器加載index.html
文件時會動態執行腳本,把樣式使用style
標籤插入到DOM
中。
咱們能夠在main.bundle.js
中找到base.css
link
標籤引入樣式style-loader
高版本已經不支持link
標籤插入文件樣式了,由於若是在一個js
文件引入多個css
文件會生成多個link
標籤,而html
中每個link
標籤都會發送一次網絡請求,因此這種方式慢慢就被棄用。
這裏咱們僅僅拿來探索一下,知道有這種方式的存在就能夠了。
首先,咱們先把style-loade
r版本降到0.20.0
,而後更改配置
module: { rules: [{ test: /\.css$/, use: [{ loader: 'style-loader/url' }, { loader: 'file-loader' }] }] },
而後打包
參考:
https://blog.csdn.net/TyrionJ/article/details/79288287
css
文件分離出來若是須要單獨把 CSS
文件分離出來,咱們須要使用mini-css-extract-plugin插件。
以前是使用extract-text-webpack-plugin
插件,此插件與 webpack4
不太匹配,如今使用mini-css-extract-plugin
安裝mini-css-extract-plugin
npm i mini-css-extract-plugin --save-dev
引入 optimize-css-assets-webpack-plugin
插件來實現 css
壓縮
npm install optimize-css-assets-webpack-plugin --save-dev
安裝 sass
依賴:
npm i node-sass sass-loader --save-dev
爲 CSS
加上瀏覽器前綴,安裝postcss-loader和autoprefixer依賴:
npm install postcss-loader autoprefixer --save-dev
更改配置文件:
const path = require('path') const { CleanWebpackPlugin } = require('clean-webpack-plugin') const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin const HtmlWebpackPlugin = require('html-webpack-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 將css單獨打包成文件 const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') module.exports = { entry: { main: './css-handle/app.js' }, output: { path: path.resolve(__dirname, 'build'), // 打包文件的輸出目錄 filename: '[name].bundle.js', // 代碼打包後的文件名 publicPath: './', // 引用的路徑或者 CDN 地址 chunkFilename: '[name].js' // 代碼拆分後的文件名 }, module: { rules: [{ test: /\.(sa|sc|c)ss$/, // 針對 .scss 或者 .css 後綴的文件設置 loader use: [{ loader: 'style-loader' }, { /** webpack loader used always at the end of loaders list */ loader: MiniCssExtractPlugin.loader }, { loader: 'css-loader', options: { importLoaders: 2 // 一個css中引入了另外一個css,也會執行以前兩個loader,即postcss-loader和sass-loader } }, { // 使用 postcss 爲 css 加上瀏覽器前綴 loader: 'postcss-loader', options: { plugins: [require('autoprefixer')] } }, { loader: 'sass-loader' // 使用 sass-loader 將 scss 轉爲 css }] }] }, // 拆分代碼配置項 optimization: { splitChunks: { chunks: 'all', minSize: 30000, maxSize: 0, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { common: { name: 'common', minSize: 0, //表示在壓縮前的最小模塊大小,默認值是 30kb,若是沒設置爲0,common模塊就不會抽離爲公共模塊,由於原始大小小於30kb minChunks: 2, // 最小公用次數 priority: 5, // 優先級 reuseExistingChunk: true // 公共模塊必開啓 }, vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } } }, plugins: [ new CleanWebpackPlugin(), // 會刪除上次構建的文件,而後從新構建 new BundleAnalyzerPlugin(), new HtmlWebpackPlugin({ // 打包輸出HTML title: '自動生成 HTML', minify: { // 壓縮 HTML 文件 removeComments: true, // 移除 HTML 中的註釋 collapseWhitespace: true, // 刪除空白符與換行符 minifyCSS: true // 壓縮內聯 css }, filename: 'index.html', // 生成後的文件名 template: path.resolve(__dirname, 'index.html'), // 根據此模版生成HTML文件 chunks: ['main'] // entry中的main入口才會被打包 }), new MiniCssExtractPlugin({ filename: '[name].css', chunkFilename: '[id].css' }), new OptimizeCssAssetsPlugin({ assetNameRegExp: /\.css$/g, cssProcessor: require('cssnano'), // 用於優化\最小化 CSS 的 CSS 處理器,默認爲 cssnano cssProcessorOptions: { safe: true, discardComments: { removeAll: true } }, // 傳遞給 cssProcesso canPrint: true // 布爾值,指示插件是否能夠將消息打印到控制檯,默認爲 true }) ] }
打包測試:
沒有配置分離以前,樣式文件會打包到入口js
文件中,而後在瀏覽器加載執行js
動態添加style
或者link
樣式。配置分離css
打包後就不同了,css、scss
文件合併成一個css
文件獨立出來,而後link
引入到html
中,並不會由js
動態引入。
html { font-size: 16px; background-color: red } *,body { margin: 0; padding: 0 } html { background-color: #000 } .example { display: grid; -webkit-transition: all .5s; transition: all .5s; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background: -webkit-gradient(linear,left top,left bottom,from(#fff),to(#000)); background: linear-gradient(180deg,#fff,#000) }
若是咱們把下面代碼註釋掉
<!-- <link href="./main.css" rel="stylesheet"> -->
而後再瀏覽器打開index.html
證明樣式文件已經獨立,不禁js入口文件動態加載。可是樣式文件仍是打包到了入口文件中。