webpack4 學習 --- 使用loader處理靜態資源


  webpack 是利用loader 來處理各種資源的,wepback的配置基本上就是為各種資源文件,指定不同類型的loader。

  1,處理css

  最基本的css 處理loader 是css-loader , style-loader.  css-loader 處理的是css 中的@import 和url, 根據路徑(相對路徑)找到相應的資源,但它不處理具體的資源,比如,img, 是由file-loader或url-loader 來處理的,這個以后再說. style-loader則是把打包后的css文件插入到html中,具體的方法是,它會生成一個內聯的style 標簽,然后把css注入到這個style標簽中,它實現了模塊熱更新,修改css樣式的時候,頁面不會強制刷新,就能看到變化。那就npm install css-loader  style-loader --save-dev 安裝它們。 安裝完成后,在webpack中進行配置。配置文件中有一個module屬性,module 屬性下面有一個rules 屬性,它是一個數組,loaders 的配置寫在它的里面,每一個配置項都是一個對象,test 屬性, 值是正則表達式,指明要處理哪種文件,use 屬性,使用哪一種loader, 最簡單的配置如下

const htmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,  // 正則表達式,指明要處理的文件類型
                use: ['style-loader', 'css-loader']  // 處理資源所使用的loader, 要注意loader的順序,從右向左執行
            }
        ]
    },
    devServer: {
        contentBase:'build', 
        proxy: {
            '/api': 'http://102.03.34.58/api'
        },
        port: 9000,  // 設置端口號
        stats: 'errors-only', // 只有產生錯誤的時候,才顯示錯誤信息,日志的輸出等級是error.
        overlay: true // 當有編譯錯誤的時候,在瀏覽器頁面上顯示。
    },
    plugins: [
        new htmlWebpackPlugin()
    ]
}

  寫一點css樣式,看配置有沒有生效,在src 目錄下,新建一個css文件夾,里面寫一個style.css文件,隨便寫一點樣式,

body {
  background: blue;
}

  然后在index.js 中引入import ‘./css/style.css’.

// 引入css 樣式
import './css/style.scss';

import component from './component';
document.body.appendChild(component())

  npm run dev 啟動服務器,可以看到頁面有了背景色,這時我們可以隨便更改body的背景色,頁面也會時時做出了變化,非常方便開發。

  當然,你可能使用css 預處理器, less, sass stylus等, 這也簡單,安裝相應的loader 就可以了,

  less: npm install less less-loader --save-dev,  

  sass: npm install node-sass, sass-loader --save -dev,

  stylus, npm install stylus, stylus-loader --save-dev,

  然后在use中增加一條相應的loader

 rules: [
            {
                test: /\.css$/,  // 正則表達式,指明要處理的文件類型
                use: ['style-loader', 'css-loader']  // 處理資源所使用的loader, 要注意loader的順序,從右向左執行
            },
            {
                test: /\.less$/, 
                use: ['style-loader', 'css-loader', 'less-loader']
            },
            {
                test: /\.scss$/, 
                use: ['style-loader', 'css-loader', 'sass-loader']
            },
            {
                test: /\.styl$/, 
                use: ['style-loader', 'css-loader', 'stylus-loader']
            }
        ]

  最后再來說一下PostCSS,  它的配置稍微麻煩一點,因為PostCSS是由插件來起作用的,使用哪個功能,就要安裝哪個插件,如果只安裝postcss-loader, 它並不起作用,這和babel-loader一樣, 比如要使用添加瀏覽器廠商前綴的功能, 在安裝postcss, postcss-loader 后,還要安裝對應的插件autoprefixer ,   npm install postcss, postcss-loader, autoprefixer --save-dev.  安裝完成后,就要進行配置。對於純css 來說,我們最先使用postcss-loader, 所以postcss-loader要放到最右邊,但是又不能只寫一個postcss-loader 放在那里,因為它自己不起作用,需要對postcss-loader進行配置。配置的方式有兩種,一種是在webpack的配置文件中,一個是單獨給postcss寫一個配置文件。

  如果在wepback的配置文件中配置postcss-loader,那postcss-loader 就不能是一個字符串了,要是一個對象, loader屬性 是我們指定的loader, options 就是我們指定的配置項,對於postcss-loader 來說,它的配置項是plugins, 使用到的插件, 是一個函數,返回一個數組,數組中就包括用到的插件。

{
                test: /\.css$/,  
                use: ['style-loader', 'css-loader',
                    {   // 使用對象對postcss-loader進行配置,對象有兩個屬性loader, options 
                        // loader屬性就是指定使用的loader, options 就是該loader的配置項,也是一個對象
                        loader: 'postcss-loader', 
                        options: {
                            plugins: () => ([
                                require('autoprefixer')()
                            ])
                        }
                    }
                ]  
            }

  但是當我們使用很多插件進行開發,這樣在配置文件中進行配置就很麻煩了,也會導致配置文件比較龐大,這時就要使用PostCSS配置文件,它的配置文件有很多格式,json, yml, js的都可以,有興趣的可以看一下官方文檔。我在這里就使用postcss.config.js. 在項目根目錄下建立一個postcss.config.js 文件,它的格式如下,module-export 出一個帶有plugins屬性的對象。plugins屬性也是一個對象,屬性名就是使用的插件的名稱,屬性值是一個對象,對這個插件的配置。

module.exports = {
  plugins: {
    "autoprefixer": {
      browsers: [
          // 加這個后可以出現額外的兼容性前綴
          "> 0.01%"
      ]
    }
  }
}

  使用配置文件后,webpack的配置文件還原到以前的狀態,

{
                test: /\.css$/,  
                use: ['style-loader', 'css-loader', 'postcss-loader']  
            }

  現在在style.css中給body, 添加box-sizing: border-box; 看一下效果。

body {
  background: blue;
  box-sizing: border-box;
}

  打開瀏覽器控制台,可以看到添加了webkit- 的瀏覽器廠商前綴。

  當使用css 預處理的時候,它要放到預處理器loader 的后面, 也就是說,先使用預處理器loader, 再使用postcss-loader. 當然配置還是一樣的。以scss 為例

{
                test: /\.scss$/, 
                use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader']
}

   但是這里會存在一個問題,就是當樣式文件中,有@import 的時候,你會發現postcss-loader 並沒有起對import 進來的文件起作用,這時在css 文件夾中,再建一個文件夾,box.css

div {
  display: flex;
  width: 200px;
  height: 200px;
  border: 1px solid blue;
}

  然后在style.css 里面@import 引入box.css;

/* @import 語句結尾要加分號 */
@import url(box.css);  
body {
  box-sizing: border-box;
}

  打開瀏覽器控制台,找到div.css的樣式,你會發現display:flex 並沒有加前綴。

  這時要給css-loader 設置一個屬性,importLoaders, 它的值為一個數字,表示css-loader 前面有幾個loader 要處理,對於純css來說,它前面有一個loader, postcss-loader,  所以importLoaders 的取值為1. 

{
                test: /\.css$/,  
                use: ['style-loader', 
                    {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 1
                        }
                    }, 
                'postcss-loader']  
}

  但是對於css預處理器來說,css-laoder 前面有個loader, postcss-loader 和預處理器loader,所以importLoaders的取值為2.

{
                test: /\.scss$/, 
                use: ['style-loader', {
                    loader: 'css-loader',
                    options: {
                        importLoaders: 2
                    }
                }, 'postcss-loader', 'sass-loader']
}

   2,處理圖片

  處理圖片主要用到兩個loader: url-loader style-loader. url-loader的作用是把圖片轉化成base64編碼的字符串,然后內嵌到到js文件中。 file-loader 則是把圖片打包成一個個單獨的圖片文件,並返回它們的路徑。但是這里有一個問題,我想把小的圖片內嵌到js中, 大的圖片打包成一個個單獨的文件,怎么辦?這時需要對url-loader進行配置,它有一個limit屬性,取值為多少k, 表示的意思時,當小於limit時,直接把圖片打包到js中,當大於limit時,就使用file-loader 打包成一個單獨的文件,當然我們也可以給打包成的圖片起一個名字,那就要配置name屬性,當使用file-loader 生成圖片的時候,它會生成一個MD5 的hash值,我們可以利用這個hash值給文件命名,name: “[name].[hash].[ext]”, name: 要打包的圖片以前的文件名,hash file-loader 生成的hash值,ext, 打包后的圖片以前的后綴名。當然,我們想把圖片統一打包到一個文件夾中。可以name 放一個文件夾名 ‘img/[name].[hash].[ext]’

         {
                test: /\.(jpg|png|svg)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 2000,
                        name: '/images/[name].[hash].[ext]'
                    }
                }
            }

  3,處理字體

  Fonts 的處理方式和image的處理方式一致,也是url-loader, file-loader, 

{
    test: /\.(ttf|eot|woff|woff2)$/,
    use: {
        loader: "url-loader",
        options: {
            limit: 50000,
            mimetype: "application/font-woff",
            name: "./fonts/[name].[ext]"
        }
    }
}

  4, 處理js

  js的處理用到的loader 是babel-loader,babel-loader 要依賴@babel/core, 現在babel升級到7了,以前的babel-core 要改成@babel/core, 感覺babel 7 是把babel 所有功能都放到了@babel的命名空間下,所有的presets 和plugins 都以@babel 開始,然后是/, 最后才是相應的preset或plugin. 先安裝上babel-loader @babel/core再說, npm install babel-loader @babel/core --save-dev 然后在webpack的配置文件中配置一下,

 {
        test: /\.js$/,
        loader: 'babel-loader'
}

  這時執行一下npm run build, 你會發現有兩個問題,一是打包非常慢,因為 webpack 進行打包的時候,會把所有的js代碼都會打包一下,包括node_modules 下面的代碼,但是node_modules下面的代碼根本就沒有必要進行打包,所以要排除掉, 要用到 exclude 配置項,我覺得使用include 更好,include是表示要打包的代碼,我們書寫的代碼在src下面,所以include 配置成src 目錄就可以了。

{
    test: /\.js$/,
    loader: 'babel-loader',
    include: path.join(__dirname, 'src'),
    exclude: path.join(__dirname, 'node_modules'),
}

   二是打包后的代碼和以前的代碼並沒有多少不同?這是因為@babel/core 本身不起作用,而是要依賴插件,一個一個插件寫起來太麻煩,所以babel 提供了插件的集合presets @babel/preset-env, npm install @babel/preset-env --save-dev, 安裝成功后,怎么告訴babel-loader 使用presets 呢? 使用babel的配置文件 .babelrc, 在項目根目錄想建立.babelrc, 內容如下,

{
    "presets": [
        "@babel/preset-env"
    ]
}

  有時候,你想使用最新的功能,它並沒有包含在preset-env中,那就要單獨安裝babel的插件了,你想使用什么功能,就安裝什么的插件,比如使用 class properties ,就是安裝

@babel/plugin-proposal-class-properties, 然后在babel 的配置文件中配置plugins
{
    "presets": [
        "@babel/preset-env"
    ],
    "plugins": [
        "@babel/plugin-proposal-class-properties"
    ]
}

   5 配置resolve, 主要是簡化引入組件或庫的方式

    當引入css 文件的時候, 要寫import './style.css' ,文件的后綴名也要寫全,比較麻煩。不想寫后綴,怎么辦, 就要在resolve中配置extensions,'.css',  只要引入文件的時候,不想寫后綴,就要在extensions 中配哪類文件的后綴

resolve: {
    extensions: ['.css', '.js', '.json', '.vue']
}

  resolve 的配置項和module ,plugins 一個等級, 它還有一個比較常用的配置項是alias別名,當在代碼文件解析時,如果碰到一個名字,它實際指代的另外一個內容,比如vue的配置文件中,alias 配置了'vue', 當在代碼中,import vue from 'vue' 時,它引用 就是alias 中配置的vue. 還有就是當我們引入一個模塊時,層級太深, import '../../../css/index.css', 這時就可以聲明一個alias, 指代一個文件夾

resolve: {
        extensions: ['.css', '.js', '.json', '.vue'],
        alias: {
            '@': 'src'
        }
    }

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM