# loader
`webpack`默認會將**js/json**文件作為模塊進行加載和打包,其它如`less`、`scss`等除js外的其它模塊,需要`loader`給它正確的解析或轉化成為`webpack`認識的模塊。
## `loader`使用
1. 通過`npm`安裝需要使用的`loader`
2. 在`webpack.config.js`中的`modules`關鍵字下進行配置
>[success] 大部分loader我們都可以在webpack的官網中找到,并且學習對應的用法。
## 使用css
webpack將所有的文件都認為是模塊所以CSS也不例外。
創建`src/index.css`
~~~
body{
background:gold;
}
~~~
**使用`css`**
在`main.js`項目入口文件 通過`import './index.css';`
~~~
import $ from "jquery"
$("ul li:even").css({background:'red'})
$("ul li:odd").css({background:'purple'})
import './index.css'
~~~
### 報錯
~~~
ERROR in ./src/index.css 1:4
Module parse failed: Unexpected token (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> body{
| background:gold;
| }
@ ./src/main.js 5:0-20
~~~
`webpack`默認是不識別`.css`文件作為結尾的模塊,需要我們通過`loader`加載器將`.css`文件進行解釋成正確的模塊
### css-loader
安裝`npm install css-loader -D`
配置`webpack.config.js`
~~~
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry:path.join(__dirname,'./src/main.js'),
output:{
path:path.join(__dirname,'./dist'),
filename:'bundle.js'
},
plugins:[
new HtmlWebpackPlugin({
template: path.join(__dirname,'./src/index.html'),
filename: 'index.html'
})
],
module:{
rules:[
{test:/\.css$/,use:['css-loader']}
]
}
}
~~~
module表示是模塊的意思,rules是規則的意思,每個規則對應的都是一個對象,其中test字段表示是書寫正則以哪個文件名結尾,use是一個數組,表示 當前類型文件用哪種加載器解釋。
### 疑問
這次我們重新執行命令`npm start`不再報錯,但是對于css的樣式并未加載成功原因是為什么?缺失`style-loader`
為什么說是缺失`style-loader?`
css-loader 是將index.css正確解釋 為webpack的模塊,進行打包到了bundle.js,我們可以佐證,但是該樣式并未成功的顯示到瀏覽器中。
那么style-loader的作用其實就是將打包到bundle.js中的css樣式輸出到瀏覽器中,以style標簽的形式顯示。


### style-loader
安裝`npm install style-loader -D`
配置`{test:/\.css$/,use:['style-loader','css-loader']}`
注意loader的加載順序是從右向左, 即先將css文件通過css-loader 作為正確的模塊進行解釋,然后再通過style-loader進行顯示到瀏覽器中。
至此CSS文件已經完成。
### 使用less文件
安裝`npm install less-loader less -D`
配置:`{test:/\.less$/,use:['style-loader','css-loader','less-loader']}`
注意,我們需要借助于less編譯。因為less-loader 依賴less。
### 使用sass文件
安裝`npm install sass-loader node-sass -D`
配置:`{test:/\.scss$/,use:['style-loader','css-loader','sass-loader']}`
~~~
rules:[
{test:/\.css$/,use:['style-loader','css-loader']},
{test:/\.less$/,use:['style-loader','css-loader','less-loader']},
{test:/\.scss$/,use:['style-loader','css-loader','sass-loader']},
]
~~~
### 注意
對正則中的.號表示任意字符,千萬小心最好把它轉義一下,再來使用。
### 項目源碼
`git clone https://github.com/highh5/webpack.git -b lesson-04`
## 圖片處理
安裝`npm install url-loader -D`
配置:`{test:/\.(jpg|jpeg|gif|png|webp)$/,use:['url-loader']},`
放置一張圖片到src目錄圖片大小為13.54kb
:-: 
我們給a.scss指定body的背景是這張圖片
~~~
$color:green;
body{
background: url("./avatar.jpg");
}
~~~
打開瀏覽器后發現圖片是以base64進行編碼了。什么是base64編譯的圖片呢?通俗的講,圖片不再像以前通過外鏈的形式打開,而是內嵌在網頁上了。圖片越大base64的編碼信息越多。也就是說越大的圖片會導致我們的代碼越來越長。這是不是好事呢?
答案: 肯定不是很好,我們期望網頁打開越快越好,如果網站當中所有的圖片全是以base64來進行編碼,那么會導致首頁代碼體積越大,那么打開速度也不會很快,相反可能會很卡。
我們一般可以讓小圖片使用base64進行加載,這樣既能讓圖片快速加載,又會減少http請求。至于大圖片我們一般就直接以往常的外鏈形式存在即可。
### 解決問題
修改loader配置項,limit表示小于后面的1000 byte即接近1kb,用base64顯示。超過的限制的話通過外鏈來讀取圖片(需要安裝file-loader 文件加載器)
`npm install file-loader -D`
~~~
{
test: /\.(jpg|jpeg|gif|png|webp)$/, use: [{
loader: 'url-loader',
options:{
limit:1000,
name:'[name].[hash:8].[ext]'
}
}]
},
~~~
最終圖片被正確解釋出來
~~~
body {
background: url(avatar.9d23d463.jpg);
}
~~~
# ES6 轉 ES5
## 安裝
`npm install babel-core babel-loader@7.1.5 babel-plugin-transform-runtime babel-preset-env babel-preset-stage-0 -D`
## 配置loader
~~~
{test:/\.js/,use:['babel-loader'],exclude:/node_modules/}
~~~
exclude表示排除掉 node\_modules下載的依賴項。這樣可以加速網站開發,而且我們也只需要對我們的項目src源文件進行編譯即可。
## 新增.babelrc文件
~~~
{
"presets":[“env","stage-0"],
"plugins":["transform-runtime"]
}
~~~
## 修改main.js使用es6語法
~~~
class Person {
constructor(){
}
}
var p = new Person();
~~~
## 執行命令編譯
`npm start`
編譯后的結果接近在1335行
~~~
\n\n var Person = function Person() {\n (0, _classCallCheck3.default)(this, Person);\n};\n\nvar p = new Person();\n\n
~~~
**至此關于webpack的基本配置已經到這里。**
## 項目源碼
`git clone https://github.com/highh5/webpack.git -b lesson-05`
## 解釋
`babel-present-env` 僅僅包括 b`abel-present-2015`、2016、2017,不包括:`babel-stage-x`,也不包括 `babel-polyfill`
`babel-present-env` 僅僅轉換 新版的語法 如:箭頭函數,并不轉換新版api 如:Array.include轉換新版api及抹平瀏覽器之間的差異(兼容ie)需要 babel-polyfill
`babel-polyfill`會污染全局,比較暴力。而`babel-plugin-transfrom-runtime`是哪里需要就給哪里轉換。
`babel-plugin-transform-runtime`主要做了一下三件事:
當你使用 `generators/async`函數時,自動引入`babel-runtime/regenerator` (使用 regenerator 運行時而不會污染當前環境) 。
自動引入`babel-runtime/core-js`并映射 ES6 靜態方法和內置插件(實現polyfill的功能且無全局污染,但是實例方法無法正常使用,如`“foobar”.includes(“foo”) )`。
移除內聯的`Babel helper` 并使用模塊`babel-runtime/helpers` 代替(提取babel轉換語法的代碼)。
## 參考文檔
[https://segmentfault.com/a/1190000010468759](https://segmentfault.com/a/1190000010468759)