1. 程式人生 > >webpack最佳入門實踐系列(4)

webpack最佳入門實踐系列(4)

例如 embedded 文件的 輸出 RM truct 來安 時間 rop

7.使用字體

7.1.安裝字體庫-font-awesome

我們通過npm來安裝字體

npm install font-awesome --save  

這個時候,我們的package.json配置文件變成這樣:

{
  "name": "code",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack",
    "start": "webpack-dev-server",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^0.28.7",
    "file-loader": "^1.1.5",
    "html-webpack-plugin": "^2.30.1",
    "style-loader": "^0.19.0",
    "url-loader": "^0.6.2",
    "webpack": "^3.10.0",
    "webpack-dev-server": "^2.9.7"
  },
  "dependencies": {
    "font-awesome": "^4.7.0"
  }
}

  

註意:我們在安裝第三方包的時候,可以使用下面兩條命令

npm install font-awesome --save

以及

npm install font-awesome --save-dev
這兩條命令的區別是,--save 安裝的是項目依賴,會把當前安裝的包一起打包隨著項目發布到線上,而--save-dev安裝的包屬於開發依賴,不會和項目一起打包發布到線上,例如,像webpack-dev-server這樣的包,我們只是在本地開發的時候使用,方便調試,而不需要發布到線上的,通常我們都會作為開發依賴安裝,像font-awesome這樣的包,我們線上的網頁也會使用,所以會一起打包發布,所以通常我們都會作為項目依賴安裝,開發依賴包的安裝信息在package.json中devDependencies這個屬性下面,項目依賴包的安裝信息在package.json中的dependencies屬性下面

7.2.使用字體庫

在index.js 文件中引入

// 引入帶有字體的css文件,用來測試webpack是否支持字體大包
import "font-awesome/css/font-awesome.css"

這個時候,我們通過npm start命令來啟動,查看效果,此時會報一個熟悉的錯誤

RROR in ./node_modules/font-awesome/fonts/fontawesome-webfont.ttf?v=4.7.0
Module parse failed: Unexpected character ‘‘ (1:0)
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
 @ ./node_modules/css-loader!./node_modules/font-awesome/css/font-awesome.css 6:645-696
 @ ./node_modules/font-awesome/css/font-awesome.css
 @ ./src/index.js
 @ multi (webpack)-dev-server/client?http://localhost:8080 ./src/index.js 

錯誤的意思是我們需要使用一個loader來處理字體文件,現在去打開font-awesome.css這個文件,查看裏面到底有哪些內容(這個文件位置在node_modules/font-awesome/css/font-awesome.css)

@font-face {
  font-family: ‘FontAwesome‘;
  src: url(‘../fonts/fontawesome-webfont.eot?v=4.7.0‘);
  src: url(‘../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0‘) format(‘embedded-opentype‘), url(‘../fonts/fontawesome-webfont.woff2?v=4.7.0‘) format(‘woff2‘), url(‘../fonts/fontawesome-webfont.woff?v=4.7.0‘) format(‘woff‘), url(‘../fonts/fontawesome-webfont.ttf?v=4.7.0‘) format(‘truetype‘), url(‘../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular‘) format(‘svg‘);
  font-weight: normal;
  font-style: normal;
} 

通過上面font-awesome文件的內容,我們知道了它引入了它上級文件夾fonts中的字體文件,這些字體文件包括:.eot、.svg、.ttf、.woff、.woff2等格式,錯誤信息告訴我們的就是webpack不支持打包這些格式的文件,那麽,我們應該使用什麽loader來讓webpack支持打包這些文件呢?

讓我們來回顧一下file-loader做的事情

1. 將文件移動到輸出目錄
2. 自動處理url後面的文件路徑,得到一個最終的引用路徑

當文件被移動到輸出目錄,並且有一個最終正確路徑的時候,我們就可以正確使用這個文件了,所以,我們嘗試使用file-loader來支持上面那些格式的字體文件

在webpack中增加配置,通過設置字體格式的匹配規則來使用file-loader,原理和處理圖片一樣

 // 處理文字
{
    test: /\.(eot|svg|ttf|woff|woff2)$/,
    use: [‘file-loader‘]
} 

接下來,我們通過命令打包

npm run dev

這個時候,會發現dist這個輸出目錄下已經多出來幾個字體文件了

我們接下來去測試,我們的字體能不能正常使用,我們在src下面index.html文件中輸入以下內容,引入圖標

<div id="app">
    <i class="fa fa-bath" aria-hidden="true"></i>
    <i class="fa fa-envelope-open" aria-hidden="true"></i>
    <i class="fa fa-microchip" aria-hidden="true"></i>
    <i class="fa fa-user-circle-o" aria-hidden="true"></i>
</div> 

然後,我們需要再次運行命令打包

npm run dev

文件打包出來後,我們直接運行html文件,註意:這個時候不要通過服務器去訪問,直接本地瀏覽器打開就好

打開後,如果看到我們引入的圖標,證明webpack已經正常支持引入字體了

8.babel相關

8.1.babel是什麽?

Babel 是一個 JavaScript 編譯器,它使用非常廣泛,可以將es6轉換成es5,從而在一些不支持es6的瀏覽器中運行,這意味著你寫es6代碼的時候就不需要去關心瀏覽器是否支持es6

點擊進入babel中文地址

點擊進入babel官方地址

8.2.使用babel

我們新建一個babel-demo的目錄來演示bebel的使用,進入到babel-demo目錄後,運行命令初始化項目

npm init -y

這條命令的作用是在babel-demo目錄下生成一個package.json的文件

接下來,我們需要安裝babel-cli

npm install --save-dev babel-cli

  

babel-cli是命令行工具,安裝以後我們就可以在命令行中通過babel命令來轉碼

安裝好後,我們寫一段代碼來測試一下babel的編譯轉碼功能,在babel-demo目錄下新建index.js文件,編寫下面代碼:

() => console.log("hello nodeing.com")

  

接下來,通過babel命令去編譯index.js

./node_modules/.bin/babel index.js

  

如果你想每次運行babel的時候都輸 ./node_modules/.bin/babel這麽一長串命令, 你可以把這個命令配置到package.json中

{
  "name": "babel-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "./node_modules/.bin/babel index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-cli": "^6.26.0"
  }
}

  

這個時候,我們通過npm的命令來啟動編譯

npm run build

  

運行後的結果,原樣輸出了index.js中的內容,為什麽babel並沒有編譯我們的index.js文件呢?

原因在於,babel是基於插件的,插件就是提供的一些擴展功能,如果沒有告訴babel用哪個插件來做事情,那麽babel就不會處理

8.3.babel插件

前面我們講到,babel是基於插件的,做不同的事情需要不同的插件,這樣讓babel非常靈活並且強大

點擊打開babel插件文檔頁,中文地址

點擊打開babel插件文檔頁,英文地址

我們去找到transform-es2015-arrow-functions這個插件,點進去查看它的使用,這個插件的功能是幫助我們把es2015(es6)的箭頭函數編譯成es5代碼

下面我們來安裝這個插件

npm install --save-dev babel-plugin-transform-es2015-arrow-functions

  

安裝好以後,我們需要在babel-demo目錄下新建.babelrc文件,這個文件就是babel的配置文件,我們在這個配置文件中增加配置項

{
    "plugins": [
      "transform-es2015-arrow-functions"
    ]
}

  

然後,運行npm命令,查看效果

npm run build

  

運行結果:

(function () {
  _newArrowCheck(this, _this);

  return console.log(1);
}).bind(this);

  

接下來,我們去修改index.js 文件,增加其他的es6語法

() => console.log(1)

class demo{}

  

再去執行npm run build命令,得到的效果也是原樣輸出,這個原因和前面我們遇到的一樣,它需要安裝另一個插件才能讓babel工作起來,要不然就什麽都不做

npm install --save-dev babel-plugin-transform-es2015-classes

  

安裝好後,同樣需要去修改.babelrc文件,增加配置

{
    "plugins": [
      "transform-es2015-arrow-functions",
      "transform-es2015-classes"
    ]
}

  

接下來就可以運行npm run build命令來查看效果了

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

(function () {
  return console.log(1);
});

let demo = function demo() {
  _classCallCheck(this, demo);
};

  

以上就是babel的插件使用方法

8.4.babel的preset

通過插件的學習,我們知道了babel要去解析轉換es6語法,需要安裝對應的插件,我們只是使用到了兩個es6的語法就裝了兩個插件,當我們需要使用很多es6語法的時候,那就需要裝非常多的插件,這樣顯得非常麻煩,那麽有沒有簡便點的方法呢?

babel通過preset來解決我們上面提出的問題,preset叫做預設,意思就是說預先設置一些常用的語法配置,把一批常用的相關的插件打包來滿足我們的開發,例如:我們處理es6語法的時候,我們就把和es6相關的語法插件打包在一起,組成一個預設,這個預設叫做es2015,所以,當我們下載一個es2015這個預設的時候,本質上就是去下載一批和es6相關的語法插件,這樣我們就不用每次去下載配置插件了

安裝preset-es2015

npm install babel-preset-es2015 --save-dev

  

安裝好後,需要去修改.babelrc配置文件

{
    "presets": [
        "es2015"
    ]
}

  

最後,通過npm run build命令,查看編譯結果

8.5.webpack和babel

讓我們把目錄切換到webpack-demo目錄,修改webpack-demo下的index.js加入下面一段es6代碼

// 測試es6是否被編譯成es5
()=>console.log("hello nodeing!!!")

  

然後運行命令查看結果

npm run dev

  

在打包出來的app.js文件中查看到,我們寫的es6代碼原樣輸出,webpack並沒有把es6代碼編譯成es5

要讓es6代碼被編譯,我們需要借助babel的力量,這裏我們需要安裝babel-loader和babel-core以及處理es6語法的預設,babel-loader的作用就是將es6代碼送給babel-core處理,babel-core就是babel工作的核心api

安裝babel-core和babel-loader以及處理es6的預設

npm install babel-loader babel-core babel-preset-es2015 --save-dev

  

在webpack-demo目錄中新建.babelrc文件,增加babel配置

{
    "presets": [
        "es2015"
    ]
}

  

接下來需要在webpack.config.js文件中增加配置項

在rules規則數字中增加下面代碼

{
    test: /\.js$/,
    use:[‘babel-loader‘]
}

  

運行npm run dev命令把index.js打包成app.js,在app.js中我們查看到,原來的es6代碼已經成功轉換成es5代碼了

// 測試es6是否被編譯成es5
(function () {
  return console.log("hello nodeing!!!");
});

  

8.6.優化babel-loader

當我們寫這個正則表達式 (/.js$/) 的時候,表示所有js文件都會被送babel-loader加載,然後由babel-core處理一邊,這裏包括我們安裝的很多第三方包,你會發現node_modules文件夾下會有很多的js文件,但是這些js文件已經由開發者打包好了我們可以直接使用的,並不需要我們再去處理一遍,因此,如果babel-loader再去處理的話,會浪費太多的時間,導致webpack打包編譯很慢,我們現在需要優化它。具體的做法是排除不需要再次編譯的,讓babel-loader只處理我們開發的源文件,因此,我們需要修改webpack.config.js中的配置

{
    test: /\.js$/,
    use:[‘babel-loader‘],
    exclude: path.resolve(__dirname, ‘node_modules‘)
},

  

其中,exclude: path.resolve(__dirname, ‘node_modules‘) 這條語句表示排除node_modules這個文件夾,因為這個文件夾下放的都是第三方包,並不需要我們再次用babel去編譯了

再次運行npm run dev去打包的時候會發現已經快很多了

webpack最佳入門實踐系列(4)