webpack4配置(3)-打包css/js/圖片等資源

陳小瓦發表於2019-04-16

打包css資源

使用loader

webpack可以使用各種不同loader來預處理不同格式的資源。

  1. 在專案目錄下新增檔案:

webpack4配置(3)-打包css/js/圖片等資源
編寫測試程式碼

// src/index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>Page Title</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<body>
    <div class="box"></div>
</body>
</html>
複製程式碼
// src/css/style.css
.box{
    width:50px;
    height: 50px;
    background-color: pink;
}
複製程式碼
  1. 安裝css-loaderstyle-loader
    css-loader負責讀取css檔案,然後使用style-loader將css內容注入到js裡面去,最終是以style標籤的形式嵌入到Html程式碼中
    npm i -D css-loader style-loader
  2. 更改配置檔案
module:
{
    test: /\.css$/,
    use: [
        {
            loader:'style-loader',  //以style標籤的形式嵌入到html中
            options:{  
                insertAt:top   //嵌入位置,top指頂部,不會覆蓋掉html自帶的style樣式
            }
        }
        'css-loader'  //解析css檔案
    ]
},
複製程式碼

module使用方法:

  • rules:一個陣列,存放各種Loader
  • test:正規表示式,用來匹配不同的檔名字尾
  • loader:有多種使用方法
{
    test:/\.js$/,
    loader:'babel-loader'  //只有一個loader時
}
{
    test:/\.css$/,
    use:['style-loader','css-loader']  //多個loader,從右往左載入
}
{
    test:/\.css$/,
    use:[ 
        'style-loader',          //多個loader混合使用
        {                           //loader要設定相關引數時可以使用物件
            loader:'css-loader',
            options:{
                minimize:true
            }
        }
    ]
}
複製程式碼

使用外掛MiniCssExtractPlugin

使用css-loader+style-loader的方式是將樣式打包進js檔案,然後以style標籤的形式嵌入頁面。css樣式與js檔案混在一起可能導致一些樣式混亂,所以使用外掛將css樣式統一打包進一個css檔案,然後以link標籤的形式嵌入頁面進行資源請求。
webpack3通常使用的是ExtractWebpackPlugin,但在webpack4中已不再支援,官方推薦使用MiniCssExtractPlugin進行替代。
首先安裝 :
npm i -D mini-css-extract-plugin
修改配置檔案

const miniCssExtractPlugin=require('mini-css-extract-plugin');

module.exports = {
    entry: path.join(__dirname, 'src/index.js'),
    output: {
        path: path.join(__dirname, 'dist'),
        filename:'bundle.js',
    },
    module: {
        rules:[
            {
                test: /\.css$/,
                use: [
                    {
                        loader:miniCssExtractPlugin.loader
                    },
                    'css-loader'
                ]
            }
        ]
    },
    plugins: [
        new htmlWebpackPlugin({
            template:'./src/index.html'
        }),
        new miniCssExtractPlugin({
            filename:'[name].css'   //輸出的css檔名,放置在dist目錄下
        }) 
    ]
}
複製程式碼

開啟dist/index.html,可以看到以link形式引入了css樣式。

自動新增字首

我們希望可以給css自動新增瀏覽器字首,可以使用外掛autoprefixer.

  1. 首先安裝,npm i -D postcss-loader autoprefixer
  2. postcss-loader需要一個配置檔案,在根目錄下新建postcss.config.js檔案,寫入:
module.exports={
    plugins:[require('autoprefixer')]
}
複製程式碼
  1. 配置loader
// webpack.config.js
{
    test: /\.css$/,
    use: [
        {
            loader:miniCssExtractPlugin.loader  //抽離成一個css檔案
        },
        'css-loader',    //解析css
        'postcss-loader'   //先新增字首
    ]
}
複製程式碼
  1. 編寫css測試程式碼
// src/css/style.css
.box{
    width:50px;
    height: 50px;
    background-color: pink;
    transform: rotateX(30deg);
}
複製程式碼
  1. 打包npm run build後,開啟dist/main.css,可以看到tranform已經加上了webkit字首。

壓縮css/js程式碼

使用optimize-css-assets-webpack-plugin外掛來壓縮css程式碼。

  1. 安裝 npm i -D optimize-css-assets-webpack-plugin
  2. 修改配置檔案
// webpack.config.js

const opimizeCss=require('optimize-css-assets-webpack-plugin');

module.exports = {
    optimization:{   
        minimizer:[
            new opimizeCss()
        ]   
    },
    mode:'production'
    ....
}    
複製程式碼
  1. npm run build以後開啟main.css發現已經被壓縮,但是在預設環境為production時自動壓縮的js程式碼卻不再壓縮了,我們使用uglifyjs-webpack-plugin來壓縮js程式碼。
  2. 安裝 npm i -D uglifyjs-webpack-plugin
  3. 修改配置檔案
//webpack.config.js
const uglifyJsWebpackPlugin=require('uglifyjs-webpack-plugin')

module.exports = {
    optimization:{   
        minimizer:[
            new uglifyJsWebpackPlugin({
                cache:true,  //是否快取
                parallel:true,  //是否併發打包,同時打包多個檔案
                sourceMap:true  //打包後的程式碼與原始碼的對映,方便除錯
            })
            ...
        ]
        ...
}        
複製程式碼

es6轉es5

webpack裡面使用了大量的es6語法,我們需要轉換為es5,使用babel來完成此功能。

  1. 安裝babel npm i -D babel-loader @babel/core @babel/preset-env
  2. 配置loader
{
    test:/\.js$/,
    use:[
        {
            loader:'babel-loader',
            options:{
                presets:[
                    `@babel/preset-env`  //es6轉es5
                ]
            }
        }
    ]
}
複製程式碼

打包圖片資源

在js中建立圖片引入

(1)引入的圖片需要在入口的js檔案中import進去

// index.js

import img from './img/big.jpg';  //file-loader將該圖片放入到dist下,同時返回圖片的地址
var imgElement = document.createElement('img');
imgElement.src = img;
document.body.appendChild(imgElement);
複製程式碼

(2)安裝file-loader並配置 npm i -D file-loader

// webpack.config.js

{
    test: /\.(png|jpg|gif|svg|jpeg)$/,
    loader: 'file-loader',
}
複製程式碼

在css中中引入背景圖片

與js引入圖片用法相同,不過比起file-loader,更常用的是url-loader,可以將小圖片直接base64編碼,減少http請求。 (1)安裝url-loader並配置 npm i -D url-loader

// webpack.config.js

{
    test: /\.(png|jpg|jpeg|gif|svg)$/,
    loader: 'url-loader',
    options: {
        limit: 1024,  //小於該值的圖片會使用base64編碼
        name: '[name].[hash:8].[ext]'  //打包後的圖片名稱 [ext]指圖片格式
    }
}
複製程式碼

直接在html寫入webpack4配置(3)-打包css/js/圖片等資源標籤

// src/index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>Page Title</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<body>
    <div class="box"></div>
    <img src="./img/big.png">
</body>
</html>
複製程式碼

打包後發現該圖片的地址是寫死的,並不會相對於dist,導致無法找到該圖片,使用html-withimg-loader來處理html中的圖片。
安裝並配置 npm i -D html-withimg-loader

// webpack.config.js
{
    test:/\.html$/,
    loader:'html-withimg-loader'
}
複製程式碼

再次打包執行後發現可以正確載入圖片了。

配置不同的資源路徑

現在這種配置下,所有的資源都放置在dist目錄下,看起來很混亂,我們希望js在js資料夾下,css在css資料夾下,圖片在img資料夾下,修改相關配置。

//webpack.config.js

module.exports = {
    entry: path.join(__dirname, 'src/index.js'),
    output: {
        path: path.join(__dirname, 'dist'),
        filename:'js/bundle.js', //給打包輸出的js新增一層目錄
    },
    module: {
        rules:[
            {
                test: /\.css$/,
                use: [
                    {
                        loader:miniCssExtractPlugin.loader
                    },
                    'css-loader',
                    'postcss-loader'  
                ]
            },
            {
                test:/\.js$/,  //最後會打包進輸出的js的檔案,所以不需要配置路徑
                use:[
                    {
                        loader:'babel-loader',
                        options:{
                            presets:[
                                `@babel/preset-env`
                            ]
                        },
                    }
                ]
            },
            {
                test: /\.(png|jpg)$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    name: '[name].[hash:8].[ext]',
                    //不能通過名字新增路徑,因為背景圖片還會被css處理一次,會再新增上css的路徑
                    //最後就會變成 css/img/big.1763821.png
                    outputPath:'img/',  //通過該屬性設定,打包輸出的路徑多一層
                    publicPath:'http://cdn.com'  //圖片的訪問路徑為 http://cdn.com/img/big.561361.png
                },
                
            },
            {
                test:/\.html$/,
                loader:'html-withimg-loader',  //會加上url-loader裡的outputPath
            }
        ]
    },
    plugins: [
        new htmlWebpackPlugin({
            template:'./src/index.html'
        }),
        new miniCssExtractPlugin({
            filename:'css/[name].css'  //通過名字新增一層路徑
        }),
        new cleanWebpackPlugin()
    ]
}
複製程式碼

最終npm run build後,就可以有不同的資料夾,同時index.html也正確處理了路徑。

相關文章