常見loader使用

一、raw-loader(文件原始內容轉換器)

一個能夠用於加載文件做爲字符串使用的加載器,使用UTF-8編碼。javascript

控制檯輸入:
npm i --D raw-loader

1.二、使用loader的三種方式

(1)、配置(推薦):在 webpack.config.js 文件中指定 loadercss

module.rules 容許你在 webpack 配置中指定多個 loader。 這是展現 loader 的一種簡明方式,而且有助於使代碼變得簡潔。同時讓你對各個 loader 有個全局概覽:html

複製代碼
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          }
        ]
      }
    ]
  }
複製代碼

Loaders須要單獨安裝而且須要在webpack.config.js中的modules關鍵字下進行配置,Loaders的配置包括如下幾方面:前端

複製代碼
test:一個用以匹配loaders所處理文件的拓展名的正則表達式(必須)

loader:loader的名稱(必須)

include/exclude:手動添加必須處理的文件(文件夾)或屏蔽不須要處理的文件(文件夾)(可選)

query:爲loaders提供額外的設置選項(可選)
複製代碼

(2)、內聯:在每一個 import 語句中顯式指定 loadervue

能夠在 import 語句或任何等效於 "import" 的方式中指定 loader。使用 ! 將資源中的 loader 分開。分開的每一個部分都相對於當前目錄解析。java

import Styles from 'style-loader!css-loader?modules!./styles.css';

經過前置全部規則及使用 !,能夠對應覆蓋到配置中的任意 loader。node

選項能夠傳遞查詢參數,例如 ?key=value&foo=bar,或者一個 JSON 對象,例如 ?{"key":"value","foo":"bar"}。react

儘量使用 module.rules,由於這樣能夠減小源碼中的代碼量,而且能夠在出錯時,更快地調試和定位 loader 中的問題。webpack

(3)、CLI:在 shell 命令中指定它們git

你也能夠經過 CLI 使用 loader:

webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'

這會對 .jade 文件使用 jade-loader,對 .css 文件使用 style-loader 和 css-loader。

4.三、常見的loader

4.3.一、文件

  • raw-loader 加載文件原始內容(utf-8)
  • val-loader 將代碼做爲模塊執行,並將 exports 轉爲 JS 代碼
  • url-loader 像 file loader 同樣工做,但若是文件小於限制,能夠返回 data URL
  • file-loader 將文件發送到輸出文件夾,並返回(相對)URL

4.3.二、JSON

4.3.三、轉換編譯(Transpiling)

4.3.四、模板(Templating)

  • html-loader 導出 HTML 爲字符串,須要引用靜態資源
  • pug-loader 加載 Pug 模板並返回一個函數
  • jade-loader 加載 Jade 模板並返回一個函數
  • markdown-loader 將 Markdown 轉譯爲 HTML
  • react-markdown-loader 使用 markdown-parse parser(解析器) 將 Markdown 編譯爲 React 組件
  • posthtml-loader 使用 PostHTML 加載並轉換 HTML 文件
  • handlebars-loader 將 Handlebars 轉移爲 HTML
  • markup-inline-loader 將內聯的 SVG/MathML 文件轉換爲 HTML。在應用於圖標字體,或將 CSS 動畫應用於 SVG 時很是有用。

4.3.五、樣式

  • style-loader 將模塊的導出做爲樣式添加到 DOM 中
  • css-loader 解析 CSS 文件後,使用 import 加載,而且返回 CSS 代碼
  • less-loader 加載和轉譯 LESS 文件
  • sass-loader 加載和轉譯 SASS/SCSS 文件
  • postcss-loader 使用 PostCSS 加載和轉譯 CSS/SSS 文件
  • stylus-loader 加載和轉譯 Stylus 文件

4.3.六、清理和測試(Linting && Testing)

4.3.七、框架(Frameworks)

  • vue-loader 加載和轉譯 Vue 組件
  • polymer-loader 使用選擇預處理器(preprocessor)處理,而且 require() 相似一等模塊(first-class)的 Web 組件
  • angular2-template-loader 加載和轉譯 Angular 組件

4.四、raw-loader(文件原始內容轉換器)

一個能夠用於加載文件做爲字符串使用的加載器,使用UTF-8編碼。

安裝

npm i --D raw-loader

 安裝結果:

用法一:

經過 webpack 配置、命令行或者內聯使用 loader。

複製代碼
webpack.config.js

module.exports = { module: { rules: [ { test: /\.txt$/, use: 'raw-loader' } ] } }
複製代碼

在你的項目中

import txt from './file.txt';

用法二:經過命令行(CLI)

webpack --module-bind 'txt=raw-loader'

用法三:在你的項目中

import txt from 'file.txt';

內聯使用

import txt from 'raw-loader!./file.txt';

示例:

webpack.config.json

  View Code

src/file1.txt

A loader for webpack that lets you import files as a string.

src/bar.js

複製代碼
//定義模塊
//部分依賴lodash中的join方法
import {join} from 'lodash';
//導入模塊,得到file1.txt中的文件內容,被raw-loader處理
import message from './file1.txt';

//導出一個默認模塊
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join鏈接數組將結果寫入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ')+"<br/>"+message;
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
複製代碼

運行結果:

內聯使用模塊處理器:

4.五、CSS Loader(樣式處理)

webpack提供兩個工具處理樣式表,css-loader 和 style-loader,兩者處理的任務不一樣,css-loader使你可以使用相似@import 和 url(...)的方法實現 require()的功能,style-loader將全部的計算後的樣式加入頁面中,兩者組合在一塊兒使你可以把樣式表嵌入webpack打包後的JS文件中。

  • css-loader: 加載.css文件
  • style-loader:使用<style>將css-loader內部樣式注入到咱們的HTML頁面

css-loader詳解:

https://www.npmjs.com/package/css-loader

https://www.webpackjs.com/loaders/css-loader/

style-loader詳解:

https://www.npmjs.com/package/style-loader

https://www.webpackjs.com/loaders/style-loader/

4.5.一、安裝

//安裝
npm i style-loader css-loader -D

4.5.二、配置

複製代碼
const path = require("path");

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: "bundle.js"
    },
    module: {
        rules: [
            {
                test:/\.css/,
                use:['style-loader',{
                    loader: 'css-loader',
                    options: {
                        sourceMap:true
                    }
                }]
            }
        ]
    },
    mode: "development"
};
複製代碼

4.5.三、定義樣式與引用

base.css

複製代碼
h2{
    height: 40px;
    line-height: 40px;
    background: crimson;
    color:#fff;
}
複製代碼

bar.js

複製代碼
import {join} from 'lodash';
import base from '../css/base.css';

export default function bar() {
    function component() {
        var element=document.createElement("h2");
        element.innerHTML=join(['Hello','Webpack!']);
        return element;
    }
    document.body.appendChild(component());
}
複製代碼

4.5.四、打包運行

打包:

運行:

生成代碼:

4.5.五、注意事項

  1. rules裏的數據類型爲對象,每個loader都是一個對象
  2. test表示loader要處理什麼類型的文件,這裏用了一個正則去匹配文件類型
  3. use表示要使用哪一個loader,它的值是個數組,loader的使用順序是從後往前
  4. 這個loader的意思爲,在入口文件裏找到.css類型的文件,先拿css-loader去處理成瀏覽器認識的css,再拿style-loader把處理後的css放在頁面的style標籤裏

4.六、sass-loader(加載和轉譯 SASS/SCSS 文件)

加載sass或scss文件並轉譯成css

用css-loader或raw-loader 轉換成一個JS模塊或用ExtractTextPlugin插件將樣式分隔成一個單獨文件。

安裝

npm i sass-loader node-sass --D

 

node-sass 和 webpack 是 sass-loader 的 peerDependency,所以可以精確控制它們的版本。

示例

css/baseScss.scss

複製代碼
$height:50px;
$color:#3366ff;

h2{
  background: $color;
  height: $height;
  line-height: $height;
  color: white;
  padding-left: $height/5;
}
複製代碼

 

經過將 style-loader 和 css-loader 與 sass-loader 鏈式調用,能夠馬上將樣式做用在 DOM 元素。

配置webpack.config.json

複製代碼
//webpack配置文件

//依賴node中的path模塊
var path=require('path');

//定義一個默認模塊對象
module.exports={
    //指定入口文件的位置,多入口
    entry:{
        index:"./src/index.js",
        main:"./src/main.js"
    },
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模塊名稱,佔位
        filename: "[name].bundle.js"
    },
    module: {  //模塊處理
        rules: [ //處理器
            {
                test:/\.txt$/,  //當模塊的後綴爲.txt時匹配
                use: "raw-loader"  //模塊轉換器,能夠以對象的形式指定參數
            },
            {
                test:/\.css$/,  //匹配全部css模塊
                //use表示要使用哪一個loader,它的值是個數組,loader的使用順序是從後往前
                use: ["style-loader",{
                    loader: "css-loader",  //轉換器名稱
                    options: {  //配置選項
                        modules:true,  //模塊化
                        sourceMap:true  //是否生成調試文件
                    }
                }]  //使用多個模塊轉換器
            },
            {
                test: /\.scss$/,
                use: [{
                    loader: "style-loader" // 將 JS 字符串生成爲 style 節點
                }, {
                    loader: "css-loader" // 將 CSS 轉化成 CommonJS 模塊
                }, {
                    loader: "sass-loader" // 將 Scss 編譯成 CSS
                }]
            }
        ]
    },
    mode: "development"
};
複製代碼

 

導入scss做爲模塊

複製代碼
//定義模塊
//部分依賴lodash中的join方法
import {join} from 'lodash';
//導入模塊,得到file1.txt中的文件內容,被raw-loader處理
import message from './file1.txt';
//導入樣式文件
//import '../css/baseCss.css' //導入預處理樣式文件
import '../css/baseScss.scss'

//導出一個默認模塊
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join鏈接數組將結果寫入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ')+"<br/>"+message;
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
複製代碼

打包後運行結果:

一般,生產環境下比較推薦的作法是,使用 ExtractTextPlugin 將樣式表抽離成專門的單獨文件。這樣,樣式表將再也不依賴於 JavaScript:

複製代碼
const ExtractTextPlugin = require("extract-text-webpack-plugin");

const extractSass = new ExtractTextPlugin({
    filename: "[name].[contenthash].css",
    disable: process.env.NODE_ENV === "development"
});

module.exports = {
    ...
        module
:
{
    rules: [{
        test: /\.scss$/,
        use: extractSass.extract({
            use: [{
                loader: "css-loader"
            }, {
                loader: "sass-loader"
            }],
// 在開發環境使用 style-loader
            fallback: "style-loader"
        })
    }]
}
,
plugins: [
    extractSass
]
}
;
複製代碼

4.七、url-loader(路徑處理器)

 Webpack 容許你在js文件中require圖片 , 經過 url-loader和file-loader來預處理圖片文件,將圖片轉換成base64編碼。

安裝

npm install --save-dev url-loader file-loader

用法

url-loader 功能相似於 file-loader,可是在文件大小(單位 byte)低於指定的限制時,能夠返回一個 DataURL。

import img from './image.png'

配置

複製代碼
webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192
                        }
                    }
                ]
            }
        ]
    }
}
複製代碼

示例

webpack.config.js

複製代碼
//webpack配置文件

//依賴node中的path模塊
var path=require('path');

//定義一個默認模塊對象
module.exports={
    entry:{app01:"./src/app01.js"},
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模塊名稱,佔位
        filename: "[name].bundle.js"
    },
    module: {
        rules: [
            {
                //如是文件名是gif,jpg,jpeg,bmp圖片則匹配,不分大小寫
                test:/\.(gif|jpe?g|png|bmp)/i,
                use: {
                    loader: "url-loader",
                    options: {
                        //若是圖片的大小小於1024byte(B)時轉換成dataUrl,base64編碼
                        limit:1024,
                        fallback:"responsive-loader"
                    }
                }
            }
        ]
    }
};
複製代碼

src/app01.js

複製代碼
//導入大圖片 404byte
import srcBig from '../img/big.jpg';
//導入小圖片 100Kbyte
import srcSma from '../img/small.gif';

console.log(srcBig);
console.log(srcSma)

alert("Hello App01!");

//建立大圖片DOM
var img1=document.createElement("img");
//指定url
img1.src=srcBig;
//添加到文檔中
document.body.appendChild(img1);

//建立小圖片DOM
var img2=document.createElement("img");
//指定url
img2.src=srcSma;
//添加到文檔中
document.body.appendChild(img2);
複製代碼

運行結果:

5、插件plugins

5.一、插件概要

Plugin 是用來擴展 Webpack 功能的,經過在構建流程裏注入鉤子實現,它給 Webpack 帶來了很大的靈活性。

插件是 webpack 的支柱功能。webpack 自身也是構建於,你在 webpack 配置中用到的相同的插件系統之上!插件目的在於解決 loader 沒法實現的其餘事。

webpack 插件是一個具備 apply 屬性的 JavaScript 對象。apply 屬性會被 webpack compiler 調用,而且 compiler 對象可在整個編譯生命週期訪問。

複製代碼
ConsoleLogOnBuildWebpackPlugin.js

const pluginName = 'ConsoleLogOnBuildWebpackPlugin';

class ConsoleLogOnBuildWebpackPlugin {
    apply(compiler) {
        compiler.hooks.run.tap(pluginName, compilation => {
            console.log("webpack 構建過程開始!");
        });
    }
}
複製代碼

 

compiler hook 的 tap 方法的第一個參數,應該是駝峯式命名的插件名稱。建議爲此使用一個常量,以便它能夠在全部 hook 中複用。

因爲插件能夠帶參數/選項,你必須在 webpack 配置中,向 plugins 屬性傳入 new 實例。

根據你的 webpack 用法,這裏有多種方式使用插件。

複製代碼
webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); //經過 npm 安裝
const webpack = require('webpack'); //訪問內置的插件
const path = require('path');

const config = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader'
      }
    ]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

module.exports = config;
複製代碼

5.一、HTML Webpack Plugin(建立HTML插件)

該個插件的做用是用來自動生成html頁面,既能夠生成單個頁面又能夠生成多個頁面,而且在生成前能夠給它一些的配置參數,它會按照你想要的生成方式去生成頁面。

第一步:安裝

npm i html-webpack-plugin -D

第二步:在webpack.config.js裏引入模塊

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

第三步:在webpack.config.js中的plugins對象裏new一個實例

plugins:[
  new HtmlWebpackPlugin({參數})
]

結果

複製代碼
const HtmlWebpackPlugin = require('html-webpack-plugin')
 
module.exports = {
  entry: 'index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin()
  ]
}
複製代碼

參數:

title

生成頁面的titile元素

filename

生成的html文件的文件名。默認index.html,能夠直接配置帶有子目錄

複製代碼
//webpack.config.js
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    filename: 'index1.html'//可帶子目錄'html/index1.html'
  })
]
複製代碼

template

模版文件路徑

templateParameters

{Boolean|Object|Function} 容許覆蓋模板中使用的參數

複製代碼
//webpack.config.js
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    templateParameters: {
      title: 'xxxx',
      favicon: './favicon/index.ico',
    }
  })
]
複製代碼

inject

插入的script插入的位置,四個可選值:
true: 默認值,script標籤位於html文件的body底部
body: 同true
headscript標籤位於html文件的head標籤內
false: 不插入生成的js文件,只是生成的html文件

favicon

爲生成的html文件生成一個favicon,屬性值是路徑

minify

html文件進行壓縮。屬性值是false或者壓縮選項值。默認false不對html文件進行壓縮。
html-webpack-plugin中集成的html-minifier,生成模板文件壓縮配置,有不少配置項,這些配置項就是minify的壓縮選項值。

hash

給生成的js文件尾部添加一個hash值。這個hash值是本次webpack編譯的hash值。默認false;

複製代碼
//webpack.config.js
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    hash: true
  })
]
//html
<script type="text/javascript" src="bundle.js?59a5ed17040d94df87fe">
//59a5ed17040d94df87fe是本次webpack編譯的hash值
複製代碼

cache

Boolean類型。只在文件被修改的時候才生成一個新文件。默認值true

showErrors

Boolean類型。錯誤信息是否寫入html文件。默認true

chunks

html文件中引用哪些js文件,用於多入口文件時。不指定chunks時,全部文件都引用

複製代碼
//webpack.config.js
entry: {
  index1: path.resolve(__dirname, './index1.js'),
  index2: path.resolve(__dirname, './index2.js'),
  index3: path.resolve(__dirname, './index3.js')
}
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    chunks: [index1, index2]//html文件中只引入index1.js, index2.js
  })
]
複製代碼

 

excludeChunks

與chunks相反,html文件不引用哪些js文件

複製代碼
//webpack.config.js
entry: {
  index1: path.resolve(__dirname, './index1.js'),
  index2: path.resolve(__dirname, './index2.js'),
  index3: path.resolve(__dirname, './index3.js')
}
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    excludeChunks: [index3.js]//html文件中不引入index3.js
  })
]
複製代碼

 

chunksSortMode

控制script標籤的引用順序。默認五個選項:
none: 無序
auto: 默認值, 按插件內置的排序方式
dependency: 根據不一樣文件的依賴關係排序
manual: chunks按引入的順序排序, 即屬性chunks的順序
{Function}: 指定具體的排序規則

xhtml

Boolean類型,默認falsetrue時以兼容xhtml的模式引用文件

示例:

複製代碼
plugins:[
    new HtmlWebpackPlugin({
        title:'Hello app',    /*這個值對應html裏的title*/
        template:'./src/template.html', //模板文件地址
        filename:'test1.html',  //文件名,默認爲index.html(路徑相對於output.path的值)
        inject:true,    //script標籤的位置,true/body爲在</body>標籤前,head爲在<head>裏,false表示頁面不引入js文件
        hash:true,  //是否爲引入的js文件添加hash值
        chunks:['one'], //頁面裏要引入的js文件,值對應的是entry裏的key。省略參數會把entry裏全部文件都引入
        //excludeChunks:['one'],//頁面裏不能引入的js文件,與chunks恰好相反
        minify:{    //html-webpack-plugin內部集成了html-minifier
            collapseWhitespace:true,    //壓縮空格
            removeAttributeQuotes:true, //移除引號
            removeComments:true,        //移除註釋
        },
    }),
    //生成兩個文件,分別引入兩個js文件(如今是一個文件裏引入了兩個js)
    new HtmlWebpackPlugin({
        title:'kaivon',
        template:'./src/template.html',
        hash:true,
        filename:'test2.html',
        chunks:['two']
    })
]
複製代碼

示例1:

webpack.config03.js配置文件

複製代碼
//webpack配置文件

//導入用於生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin");

//依賴node中的path模塊
var path=require('path');

//定義一個默認模塊對象
module.exports={
    entry:{app01:"./src/app03.js"},
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模塊名稱,佔位
        filename: "[hash:8].bundle.js"
    },
    module: {
    },
    plugins: [
        //建立一個插件對象,並指定參數
        new HtmlWebpackPlugin({
            //指定生成的文件路徑與名稱
            filename:"../app03.html",
            //標題
            title:"Hello App03!"
        })
    ]
};
複製代碼

arc/app03.js

alert("Hello App03!");

打包結果:

運行:

示例2:

webpack.config03.js配置文件

複製代碼
//webpack配置文件

//導入用於生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin");

//依賴node中的path模塊
var path=require('path');

//定義一個默認模塊對象
module.exports={
    entry:{app01:"./src/app03.js"},
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模塊名稱,佔位
        filename: "[hash:8].bundle.js"
    },
    module: {
    },
    plugins: [
        //建立一個插件對象,並指定參數
        new HtmlWebpackPlugin({
            //指定生成的文件路徑與名稱
            filename:"../app03.html",
            //標題
            title:"Hello App03!",
            //指定模板
            template:"./templates/tmpl03.html",
            //模板參數,容許覆蓋templates中的參數
            templateParameters:{
                content:"Hello templateParameters!",
                //重寫title
                title:"Hello App03 title!",
                key:"value"
            },
            minify:{
                removeComments:true,  //移除註釋
                collapseWhitespace:true,  //摺疊空格
                //更新請參數https://github.com/kangax/html-minifier#options-quick-reference
            }
        })
    ]
};
複製代碼

/templates/tmpl03.html 模板文件

  View Code

生成結果:

5.二、Mini-css-extract-plugin(單獨提取CSS插件)

將CSS提取爲獨立的文件的插件,對每一個包含css的js文件都會建立一個CSS文件,支持按需加載css和sourceMap

默認狀況下css是被js注入的一段style,以下所示:

只能用在webpack4中,對比另外一個插件 extract-text-webpack-plugin特色:

  • 異步加載
  • 不重複編譯,性能更好
  • 更容易使用
  • 只針對CSS

目前缺失功能,HMR(熱模塊替換)。

  HMR解釋

安裝:

npm install --save-dev mini-css-extract-plugin

使用:

複製代碼
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // 相似 webpackOptions.output裏面的配置 能夠忽略
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              // 這裏能夠指定一個 publicPath
              // 默認使用 webpackOptions.output中的publicPath
              publicPath: '../'
            },
          },
          'css-loader',
        ],
      }
    ]
  }
}
複製代碼

高級配置:

這個插件應該只用在 production 配置中,而且在loaders鏈中不使用 style-loader, 特別是在開發中使用HMR,由於這個插件暫時不支持HMR

複製代碼
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: devMode ? '[name].css' : '[name].[hash].css',
      chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
    })
  ],
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader',
        ],
      }
    ]
  }
}
複製代碼

示例:

webpack.config03.js

複製代碼
//webpack配置文件

//導入用於生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin");
//導入用於提取css的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

//依賴node中的path模塊
var path=require('path');

//定義一個默認模塊對象
module.exports={
    entry:{app01:"./src/app03.js"},
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模塊名稱,佔位
        filename: "[hash:8].bundle.js"
    },
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [{
                    loader:MiniCssExtractPlugin.loader //提取css並link
                }, {
                    loader: "css-loader" // 將 CSS 轉化成 CommonJS 模塊
                }, {
                    loader: "sass-loader" // 將 Scss 編譯成 CSS
                }]
            }
        ]
    },
    plugins: [
        //建立一個插件對象,並指定參數
        new HtmlWebpackPlugin({
            //指定生成的文件路徑與名稱
            filename:"../app03.html",
            //標題
            title:"Hello App03!",
            //指定模板
            template:"./templates/tmpl03.html",
            //模板參數,容許覆蓋templates中的參數
            templateParameters:{
                content:"Hello templateParameters!",
                //重寫title
                title:"Hello App03 title!",
                key:"value"
            },
            minify:{
                removeComments:true,  //移除註釋
                collapseWhitespace:true,  //摺疊空格
                //更新請參數https://github.com/kangax/html-minifier#options-quick-reference
            }
        }),
        //建立一個用於提取css的插件對象
        new MiniCssExtractPlugin({
            filename:"[name]_[hash:10].css",
            chunkFilename:"[id]"
        })
    ]
};
複製代碼

src/app03.js

import '../css/baseScss.scss';

alert("Hello App03!");

打包生成的結果

複製代碼
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>Hello App03 title!</title>
    <link href="dist/app01_1b7c11aa92.css" rel="stylesheet">
</head>
<body><h2>Hello templateParameters!</h2>
<script type="text/javascript" src="dist/1b7c11aa.bundle.js"></script>
</body>
</html>
複製代碼

運行結果:

5.三、clean-webpack-plugin(刪除或清理構建目錄)

在用HtmlWebpackPlugin的時候時須要把dist目錄刪掉再去看生成的文件,clean-webpack-plugin這個插件就能夠作這件事情

第一步:安裝

npm i clean-webpack-plugin --save-dev

 

第二步:在webpack.config.js裏引入模塊

const CleanWebpackPlugin=require('clean-webpack-plugin');

 

第三步:在plugins的最前面建立清理對象

複製代碼
plugins:[
new CleanWebpackPlugin(['./dist']), //這個必定要放在最上面,做用是先刪除dist目錄再建立新的dist目錄。裏面的參數爲要刪除的目錄,放在一個數組裏面
...
]
複製代碼

 

在文件夾裏打開dist所在的目錄,並在終端裏再次執行命令webpack後,會看到dist目錄先被刪除後又被建立。

關於clean-webpack-plugin插件的全部配置參數請參考:https://www.npmjs.com/package/clean-webpack-plugin

示例:

複製代碼
const CleanWebpackPlugin = require('clean-webpack-plugin'); //installed via npm
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
const path = require('path');
 
// the path(s) that should be cleaned
let pathsToClean = [
  'dist',
  'build'
]
 
// the clean options to use
let cleanOptions = {
  root:     '/full/webpack/root/path',
  exclude:  ['shared.js'],
  verbose:  true,
  dry:      false
}
 
// sample WebPack config
const webpackConfig = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        loader: 'babel-loader'
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(pathsToClean, cleanOptions),
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
}
複製代碼

6、DevServer開發服務器 

在實際開發中咱們可能會須要完成以下功能:

  1. 提供 HTTP 服務而不是使用本地文件預覽;
  2. 監聽文件的變化並自動刷新網頁,作到實時預覽;
  3. 支持 Source Map,以方便調試。

Webpack 原生支持上述第二、3點內容,再結合官方提供的開發工具 DevServer 也能夠很方便地作到第1點。 DevServer 會啓動一個 HTTP 服務器用於服務網頁請求,同時會幫助啓動 Webpack ,並接收 Webpack 發出的文件更變信號,經過 WebSocket 協議自動刷新網頁作到實時預覽。

6.一、快速開啓DevServer

安裝 DevServer:

npm i -D webpack-dev-server

安裝成功後在項目的根目錄下執行webpack-dev-server 命令, DevServer 服務器就啓動了,這時你會看到控制檯有一串日誌輸出:

Project is running at http://localhost:8080/

webpack output is served from /

如今就能夠直接訪問了

這意味着 DevServer 啓動的 HTTP 服務器監聽在 http://localhost:8080/ ,DevServer 啓動後會一直駐留在後臺保持運行,訪問這個網址你就能獲取項目根目錄下的 index.html。 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

0分鐘學會前端工程化(webpack4.0)

 

1、概要

1.一、前端工程化

隨着前端的不斷髮展與壯大,前端變得愈來愈複雜,組件化、模塊化、工程化、自動化成了前端發展中不可或缺的一部分,具體到前端工程化,面臨的問題是如何提升編碼->測試->維護階段的生產效率。

前端工程化是使用軟件工程的技術和方法來進行前端項目的開發、維護和管理。

前端工程化是依據業務特色,將前端開發的規範、流程、技術、工具、經驗等造成規範並創建成一種標準的體系。

如今的項目可能會不停的迭代,發佈就成了平常開發的一部分,前端不只要保證功能還要保證性能,傳統的一次次的發佈效率會很是低,前端工程化通常都有會藉助一些工具。

實現前端工程化的目的簡單來講就是經過流程規範、自動化工具來提高前端的開發效率、性能、質量、多人協做能力以及開發體驗,創建前端工程化是各個團隊必經的成長過程。

1.1.一、前端工程化的任務

前端不只要保證功能還要考慮性能,要減小http請求數量、壓縮、合併、預處理、規範代碼、清理、打包、轉換等工做。

前端大部分狀況下源代碼沒法直接運行,必須經過轉換後才能夠正常運行。構建就是作這件事情,把源代碼轉換成發佈到線上的可執行 JavaScrip、CSS、HTML 代碼,包括以下內容。

(1)、代碼轉換:TypeScript 編譯成 JavaScript、SCSS 編譯成 CSS 等。

(2)、文件優化:壓縮 JavaScript、CSS、HTML 代碼,壓縮合並圖片等。

(3)、代碼分割:提取多個頁面的公共代碼、提取首屏不須要執行部分的代碼讓其異步加載。

(4)、模塊合併:在採用模塊化的項目裏會有不少個模塊和文件,須要構建功能把模塊分類合併成一個文件。

(5)、自動刷新:監聽本地源代碼的變化,自動從新構建、刷新瀏覽器。

(6)、代碼校驗:在代碼被提交到倉庫前須要校驗代碼是否符合規範,以及單元測試是否經過。

(7)、自動發佈:更新完代碼後,自動構建出線上發佈代碼並傳輸給發佈系統。

構建實際上是工程化、自動化思想在前端開發中的體現,把一系列流程用代碼去實現,讓代碼自動化地執行這一系列複雜的流程。 構建給前端開發注入了更大的活力,解放了咱們的生產力。

1.二、前端工程化工具

歷史上前後出現一系列構建工具,它們各有其優缺點。因爲前端工程師很熟悉 JavaScript ,Node.js 又能夠勝任全部構建需求,因此大多數構建工具都是用 Node.js 開發的。

構建工具的主要功能就是實現自動化處理,例如對代碼進行檢查、預編譯、合併、壓縮;生成雪碧圖、sourceMap、版本管理;運行單元測試、監控等,固然有的工具還提供模塊化、組件化的開發流程功能。

 

若是把工具按類型分能夠分爲這三類:

(一)、基於任務運行的工具:Grunt、Gulp

它們會自動執行指定的任務,就像流水線,把資源放上去而後經過不一樣插件進行加工,它們包含活躍的社區,豐富的插件,能方便的打造各類工做流。

(二)、基於模塊化打包的工具:Browserify、Webpack、rollup.js

有過 Node.js 開發經歷的應該對模塊很熟悉,須要引用組件直接一個 require 就 OK,這類工具就是這個模式,還能夠實現按需加載、異步加載模塊。

(三)、整合型工具:Yeoman、FIS、jdf、Athena、cooking、weflow

使用了多種技術棧實現的腳手架工具,好處是即開即用,缺點就是它們約束了技術選型,而且學習成本相對較高。

1.2.一、Grunt

Grunt([ɡrʌnt]做呼嚕聲) 生態系統很是龐大,而且一直在增加。因爲擁有數量龐大的插件可供選擇,所以,你能夠利用 Grunt 自動完成許多事,而且花費不多的代價。若是找不到你所須要的插件,那就本身動手創造一個 Grunt 插件,而後將其發佈到 npm 上吧。

官網:https://gruntjs.com/

GitHub:https://github.com/gruntjs/

中文網:https://www.gruntjs.net/

對於須要反覆重複的任務,例如壓縮(minification)、編譯、單元測試、linting等,自動化工具能夠減輕你的勞動,簡化你的工做。當你在 Gruntfile 文件正確配置好了任務,任務運行器就會自動幫你或你的小組完成大部分無聊的工做。

Grunt 是老牌的構建工具,特色是配置驅動,你須要作的就是了解各類插件的功能,而後把配置整合到 Gruntfile.js 中,下面是配置例子:

複製代碼
module.exports = function(grunt) {
    grunt.initConfig({
        jshint: {
            files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
            options: {
                globals: {
                    jQuery: true
                }
            }
        },
        watch: {
            files: ['<%= jshint.files %>'],
            tasks: ['jshint']
        }
    });

    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.registerTask('default', ['jshint']);
};
複製代碼

Grunt 缺點也是配置驅動,當任務很是多的狀況下,試圖用配置完成全部事簡直就是個災難;再就是它的 I/O 操做也是個弊病,它的每一次任務都須要從磁盤中讀取文件,處理完後再寫入到磁盤,例如:我想對多個 less 進行預編譯、壓縮操做,那麼 Grunt 的操做就是:

讀取 less 文件 -> 編譯成 css -> 存儲到磁盤 -> 讀取 css -> 壓縮處理 -> 存儲到磁盤

這樣一來當資源文件較多,任務較複雜的時候性能就是個問題了。

1.2.二、Gulp

Gulp(ɡʌlp狼吞虎嚥地吃,吞嚥)是一個基於流的自動化構建工具。 除了能夠管理和執行任務,還支持監聽文件、讀寫文件。

中文網:https://www.gulpjs.com.cn/

官網:https://gulpjs.com/

特色:

易於使用:經過代碼優於配置的策略,Gulp 讓簡單的任務簡單,複雜的任務可管理。

構建快速:利用 Node.js 流的威力,你能夠快速構建項目並減小頻繁的 IO 操做。

插件高質:Gulp 嚴格的插件指南確保插件如你指望的那樣簡潔高質得工做。

易於學習:經過最少的 API,掌握 Gulp 不太費力,構建工做盡在掌握:如同一系列流管道。

Gulp 被設計得很是簡單,只經過下面5種個方法就能夠勝任幾乎全部構建場景:

經過 gulp.task 註冊一個任務;

經過 gulp.run 執行任務;

經過 gulp.watch 監聽文件變化;

經過 gulp.src 讀取文件;

經過 gulp.dest 寫文件。

Gulp 的最大特色是引入了流的概念,同時提供了一系列經常使用的插件去處理流,流能夠在插件之間傳遞

Gulp 特色是代碼驅動,寫任務就和寫普通的 Node.js 代碼同樣:

複製代碼
var gulp = require('gulp');
var pug = require('gulp-pug');
var less = require('gulp-less');
var minifyCSS = require('gulp-csso');

gulp.task('html', function(){
    return gulp.src('client/templates/*.pug')
        .pipe(pug())
        .pipe(gulp.dest('build/html'))
});

gulp.task('css', function(){
    return gulp.src('client/templates/*.less')
        .pipe(less())
        .pipe(minifyCSS())
        .pipe(gulp.dest('build/css'))
});

gulp.task('default', [ 'html', 'css' ]);
複製代碼

再一個對文件讀取是流式操做(Stream),也就是說一次 I/O 能夠處理多個任務,仍是 less 的例子,Gulp 的流程就是:

讀取 less 文件 -> 編譯成 css -> 壓縮處理 -> 存儲到磁盤

Gulp 做爲任務類型的工具沒有明顯的缺點,惟一的問題可能就是完成相同的任務它須要寫的代碼更多一些,因此除非是項目有歷史包袱(原有項目就是基於 Grunt 構建)在 Grunt 與 Gulp 對比看來仍是比較推薦 Gulp!

適用場景:

經過上面的介紹能夠看出它們側重對整個過程的控制管理,實現簡單、對架構無要求、不改變開發模式,因此很是適合前端、小型、須要快速啓動的項目。

1.2.三、Yeoman

Yeoman([ˈjoʊmən]自耕農,自由民; 義勇騎兵隊成員,young+man)的目的不只是要爲新項目創建工做流,同時仍是爲了解決前端開發所面臨的諸多嚴重問題,例如零散的依賴關係。
Yeoman是Google的團隊和外部貢獻者團隊合做開發的,他的目標是經過Grunt(一個用於開發任務自動化的命令行工具)和Bower(一個HTML、CSS、Javascript和圖片等前端資源的包管理器)的包裝爲開發者建立一個易用的工做流。

Yeoman是一個強健的腳手架與構建工具,庫,及工做流程的組合,幫你網頁開發者快速建立出漂亮並且引人入勝的網頁程序,Yeoman幫助咱們建立項目,提供更好的工具來使咱們的項目更多樣化。

Yeoman提供generator系統,一個generator是一個插件,在咱們在一個完整的項目上使用‘yo’命令時,會運行該generator。經過這些官方的Generators,推出了Yeoman工做流,工做流是一個健壯、有本身特點的客戶端堆棧,包含能快速構建漂亮的網絡應用的工具和框架。Yeoman提供了負責開始項目開發的一切,沒有任何讓人頭痛的手動配置。

Yeoman主要提供了三個工具:腳手架(yo),構建工具(grunt),包管理器(bower)。這三個工具是分別獨立開發的,可是須要配合使用,來實現咱們更高效的工做流模式。

小結:

在 Npm Script 和 Grunt 時代,Web 開發要作的事情變多,流程複雜,自動化思想被引入,用於簡化流程;

在 Gulp 時代開始出現一些新語言用於提升開發效率,流式處理思想的出現是爲了簡化文件轉換的流程,例如將 ES6 轉換成 ES5。

在 Webpack 時代因爲單頁應用的流行,一個網頁的功能和實現代碼變得龐大,Web 開發向模塊化改進。

這些構建工具都有各自的定位和專一點,它們之間既能夠單獨地完成任務,也能夠相互搭配起來彌補各自的不足。 在瞭解這些常見的構建工具後,你須要根據本身的需求去判斷應該如何選擇和搭配它們才能更好地完成本身的需求。

通過多年的發展, Webpack 已經成爲構建工具中的首選,緣由是:

大多數團隊在開發新項目時會採用緊跟時代的技術,這些技術幾乎都會採用「模塊化+新語言+新框架」,Webpack 能夠爲這些新項目提供一站式的解決方案;

Webpack 有良好的生態鏈和維護團隊,能提供良好的開發體驗和保證質量;

Webpack 被全世界的大量 Web 開發者使用和驗證,能找到各個層面所需的教程和經驗分享。

1.三、WebPack

webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關係圖(dependency graph),其中包含應用程序須要的每一個模塊,而後將全部這些模塊打包成一個或多個 bundle。

Webpack 是一個打包模塊化 JavaScript 的工具,在 Webpack 裏一切文件皆模塊,經過 Loader 轉換文件,經過 Plugin 注入鉤子,最後輸出由多個模塊組合成的文件。Webpack 專一於構建模塊化項目。

其官網的首頁圖很形象的畫出了 Webpack 是什麼,以下:

一切文件:JavaScript、CSS、SCSS、圖片、模板,在 Webpack 眼中都是一個個模塊,這樣的好處是能清晰的描述出各個模塊之間的依賴關係,以方便 Webpack 對模塊進行組合和打包。 通過 Webpack 的處理,最終會輸出瀏覽器能使用的靜態資源。

Webpack 具備很大的靈活性,能配置如何處理文件,大體使用以下:

複製代碼
module.exports = {
// 全部模塊的入口,Webpack 從入口開始遞歸解析出全部依賴的模塊
    entry: './app.js',
    output: {
// 把入口所依賴的全部模塊打包成一個文件 bundle.js 輸出 
        filename: 'bundle.js'
    }
}
複製代碼

1.3.一、Webpack的特色

把一切都視爲模塊:無論是 CSS、JS、Image 仍是 HTML 均可以互相引用,經過定義 entry.js,對全部依賴的文件進行跟蹤,將各個模塊經過 loader 和 plugins 處理,而後打包在一塊兒。

按需加載:打包過程當中 Webpack 經過 Code Splitting 功能將文件分爲多個 chunks,還能夠將重複的部分單獨提取出來做爲 commonChunk,從而實現按需加載。

優勢:

專一於處理模塊化的項目,能作到開箱即用一步到位;

經過 Plugin 擴展,完整好用又不失靈活;

使用場景不只限於 Web 開發;

社區龐大活躍,常常引入緊跟時代發展的新特性,能爲大多數場景找到已有的開源擴展;

良好的開發體驗。

缺點:

Webpack的缺點是隻能用於採用模塊化開發的項目。

上手比較難、對於新手而言須要經歷踩坑的過程。

對於Server 端渲染的多頁應用有點力不從心。

小結:

Webpack 特別適合配合 React.js、Vue.js 構建單頁面應用以及須要多人合做的大型項目,在規範流程都已約定好的狀況下每每能極大的提高開發效率與開發體驗。

1.3.二、資源

官網:https://webpack.js.org/

github:https://github.com/webpack/webpack

中文網:https://www.webpackjs.com/

深刻淺出webpack電子書:http://webpack.wuhaolin.cn/

1.3.三、工做流程

Webpack 是經過配置來實現管理,與 Grunt 不一樣的是它包含的許多自動化的黑盒操做因此配置起來會簡單不少(但遇到問題調試起來就很麻煩),一個典型的配置以下:

複製代碼
module.exports = {
    //插件項
    plugins: [commonsPlugin],
    //頁面入口文件配置
    entry: {
        index : './src/js/page/index.js'
    },
    //入口文件輸出配置
    output: {
        path: 'dist/js/page',
        filename: '[name].js'
    },
    module: {
        //加載器配置
        loaders: [
            { test: /\.css$/, loader: 'style-loader!css-loader' },
            { test: /\.js$/, loader: 'jsx-loader?harmony' },
            { test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
            { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}
        ]
    },
    //其它解決方案配置
    resolve: {
        root: '/Users/Bell/github/flux-example/src', //絕對路徑
        extensions: ['', '.js', '.json', '.scss'],
        alias: {
            AppStore : 'js/stores/AppStores.js',
            ActionType : 'js/actions/ActionType.js',
            AppAction : 'js/actions/AppAction.js'
        }
    }
};
複製代碼

 

1.3.四、搭建WebPack開發環境

(1)、安裝NodeJS

在用 Webpack 執行構建任務時須要經過 webpack 可執行文件去啓動構建任務,因此須要安裝 webpack 可執行文件。 在安裝 Webpack 前請確保你的系統安裝了5.0.0及以上版本的 Node.js。

https://nodejs.org/下載安裝

設置國內npm的鏡像

$ npm install -g cnpm --registry=https://registry.npm.taobao.org

使用時用cnpm代替npm

(2)、安裝webpack

安裝 Webpack 到全局

安裝到全局後你能夠在任何地方共用一個 Webpack 可執行文件,而不用各個項目重複安裝,安裝方式以下:

npm i -g webpack

cli:

全部cli參數:

  View Code

要安裝 Webpack 到本項目,可按照你的須要選擇如下任意命令運行:

複製代碼
# npm i -D 是 npm install --save-dev 的簡寫,是指安裝模塊並保存到 package.json 的 devDependencies
# 安裝最新穩定版
npm i -D webpack

# 安裝指定版本
npm i -D webpack@<version>

# 安裝最新體驗版本
npm i -D webpack@beta
複製代碼

2、快速上手

2.一、建立一個項目或目錄

建立一個空項目或一個空目錄,不必定須要使用IDE,這裏我使用WebStorm

2.二、初始化項目

npm init -y (-y直接跳過提問階段)

複製代碼
name - 包名.
version - 包的版本號。
description - 包的描述。
homepage - 包的官網URL。
author - 包的做者,它的值是你在https://npmjs.org網站的有效帳戶名,遵循「帳戶名<郵件>」的規則,例如:zhangsan <zhangsan@163.com>。
contributors - 包的其餘貢獻者。
dependencies / devDependencies - 生產/開發環境依賴包列表。它們將會被安裝在 node_module 目錄下。
repository - 包代碼的Repo信息,包括type和URL,type能夠是git或svn,URL則是包的Repo地址。
main - main 字段指定了程序的主入口文件,require('moduleName') 就會加載這個文件。這個字段的默認值是模塊根目錄下面的 index.js。
keywords - 關鍵字
複製代碼

package.json詳解

2.三、安裝webpack

webpack4須要安裝webpack-cli:

npm i webpack webpack-cli --save-dev

2.四、建立目錄與文件

src/bar.js

複製代碼
//定義模塊
//部分依賴lodash中的join方法
import {join} from 'lodash'

//導出一個默認模塊
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join鏈接數組將結果寫入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ');
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
複製代碼

實現使用lodash的join 鏈接字符串,在網頁中輸出字符串

依賴lodash、npm安裝lodash,在bar.js中import lodash的join方法,輸出text

npm i lodash --save

src/index.js

複製代碼
//入口文件

//導入自定義好的模塊
import bar from './bar';
//調用
bar();
複製代碼

建立配置文件webpack.config.js

複製代碼
//webpack配置文件

//依賴node中的path模塊
const path=require('path');

//定義一個默認模塊對象
module.exports={
    //指定入口文件的位置
    entry:"./src/index.js",
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件
        filename: "bundle.js"
    }
};
複製代碼

path.resolve獲取文件的路徑,_dirname爲當前模塊的絕對路徑,詳細解釋以下:

  View Code

index.html

webpack建立dist文件在dist中生成打包文件,而後再index.html中引用index.js文件

複製代碼
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello WebPack</title>
</head>
<body>
<h2>Hello WebPack</h2>
<script src="dist/bundle.js"></script>
</body>
</html>
複製代碼

2.五、使用webpack命令打包

能夠指定配置文件

webpack --config webpack.config.js

也可使用默認的配置文件

webpack

打包的結果:

  View Code

 bundle.js文件:

2.六、運行

3、核心概念與執行過程

本質上,webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關係圖(dependency graph),其中包含應用程序須要的每一個模塊,而後將全部這些模塊打包成一個或多個 bundle。

從 webpack v4.0.0 開始,能夠不用引入一個配置文件。然而,webpack 仍然仍是高度可配置的。在開始前你須要先理解幾個核心概念:

3.一、模塊(Module)

在Webpack裏一切皆模塊,一個模塊對應着一個文件。Webpack 會從配置的Entry開始遞歸找出全部依賴的模塊。

webpack把一切都視爲模塊,無論是 CSS、JS、Image 仍是 HTML 均可以互相引用。Node.js 從最一開始就支持模塊化編程。然而,在 web,模塊化的支持正緩慢到來。在 web 存在多種支持 JavaScript 模塊化的工具,這些工具各有優點和限制。webpack 基於從這些系統得到的經驗教訓,並將模塊的概念應用於項目中的任何文件。

什麼是 webpack 模塊

對比 Node.js 模塊,webpack 模塊可以以各類方式表達它們的依賴關係,幾個例子以下:

  1. ES2015 import 語句
  2. CommonJS require() 語句
  3. AMD define 和 require 語句
  4. css/sass/less 文件中的 @import 語句。
  5. 樣式(url(...))或 HTML 文件(<img src=...>)中的圖片連接(image url)

支持的模塊類型

webpack 經過 loader 能夠支持各類語言和預處理器編寫模塊。loader 描述了 webpack 如何處理 非 JavaScript(non-JavaScript) _模塊_,而且在 bundle 中引入這些依賴。 webpack 社區已經爲各類流行語言和語言處理器構建了 loader,包括:

  1. CoffeeScript
  2. TypeScript
  3. ESNext (Babel)
  4. Sass
  5. Less
  6. Stylus

3.二、入口(entry)

入口,Webpack 執行構建的第一步將從 Entry 開始,可抽象成輸入。

入口起點(entry point)指示 webpack 應該使用哪一個模塊,來做爲構建其內部依賴圖的開始。進入入口起點後,webpack 會找出有哪些模塊和庫是入口起點(直接和間接)依賴的。

每一個依賴項隨即被處理,最後輸出到稱之爲 bundles 的文件中,咱們將在下一章節詳細討論這個過程。

能夠經過在 webpack 配置中配置 entry 屬性,來指定一個入口起點(或多個入口起點)。默認值爲 ./src。

接下來咱們看一個 entry 配置的最簡單例子:

複製代碼
webpack.config.js

module.exports = {
    entry: './path/to/my/entry/file.js'
};
複製代碼

根據應用程序的特定需求,能夠以多種方式配置 entry 屬性。

多入口與多出口:

複製代碼
{
  entry: {
    app: './src/app.js',
    search: './src/search.js'
  },
  output: {
    filename: '[name].js',
    path: __dirname + '/dist'
  }
}

// 寫入到硬盤:./dist/app.js, ./dist/search.js
複製代碼

經常使用的佔位:

  1. [hash]:模塊標識符(module identifier)的 hash
  2. [chunkhash]:chunk 內容的 hash
  3. [name]:模塊名稱,key的名稱,非文件名稱
  4. [id]:模塊標識符(module identifier)
  5. [query]:模塊的 query,例如,文件名 ? 後面的字符串

3.三、出口(output)

輸出結果,在 Webpack 通過一系列處理並得出最終想要的代碼後輸出結果。

output 屬性告訴 webpack 在哪裏輸出它所建立的 bundles,以及如何命名這些文件,默認值爲 ./dist。基本上,整個應用程序結構,都會被編譯到你指定的輸出路徑的文件夾中。你能夠經過在配置中指定一個 output 字段,來配置這些處理過程:

複製代碼
webpack.config.js

const path = require('path');

module.exports = {
    entry: './path/to/my/entry/file.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-first-webpack.bundle.js'
    }
};
複製代碼

在上面的示例中,咱們經過 output.filename 和 output.path 屬性,來告訴 webpack bundle 的名稱,以及咱們想要 bundle 生成(emit)到哪裏。可能你想要了解在代碼最上面導入的 path 模塊是什麼,它是一個 Node.js 核心模塊,用於操做文件路徑。

示例:

3.四、模塊轉換器(loader)

模塊轉換器,用於把模塊原內容按照需求轉換成新內容。

loader 讓 webpack 可以去處理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 能夠將全部類型的文件轉換爲 webpack 可以處理的有效模塊,而後你就能夠利用 webpack 的打包能力,對它們進行處理。

本質上,webpack loader 將全部類型的文件,轉換爲應用程序的依賴圖(和最終的 bundle)能夠直接引用的模塊。

注意,loader 可以 import 導入任何類型的模塊(例如 .css 文件),這是 webpack 特有的功能,其餘打包程序或任務執行器的可能並不支持。咱們認爲這種語言擴展是有很必要的,由於這可使開發人員建立出更準確的依賴關係圖。

在更高層面,在 webpack 的配置中 loader 有兩個目標:

  1. test 屬性,用於標識出應該被對應的 loader 進行轉換的某個或某些文件。
  2. use 屬性,表示進行轉換時,應該使用哪一個 loader。
複製代碼
webpack.config.js

const path = require('path');

const config = {
    output: {
        filename: 'my-first-webpack.bundle.js'
    },
    module: {
        rules: [
            { test: /\.txt$/, use: 'raw-loader' }
        ]
    }
};

module.exports = config;
複製代碼

以上配置中,對一個單獨的 module 對象定義了 rules 屬性,裏面包含兩個必須屬性:test 和 use。這告訴 webpack 編譯器(compiler) 以下信息:

「webpack 編譯器,當你碰到「在 require()/import 語句中被解析爲 '.txt' 的路徑」時,在你對它打包以前,先使用 raw-loader 轉換一下。」

3.五、插件(plugins)

擴展插件,在 Webpack 構建流程中的特定時機注入擴展邏輯來改變構建結果或作你想要的事情。

loader 被用於轉換某些類型的模塊,而插件則能夠用於執行範圍更廣的任務。插件的範圍包括,從打包優化和壓縮,一直到從新定義環境中的變量。插件接口功能極其強大,能夠用來處理各類各樣的任務。

想要使用一個插件,你只須要 require() 它,而後把它添加到 plugins 數組中。多數插件能夠經過選項(option)自定義。你也能夠在一個配置文件中由於不一樣目的而屢次使用同一個插件,這時須要經過使用 new 操做符來建立它的一個實例。

複製代碼
webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 經過 npm 安裝
const webpack = require('webpack'); // 用於訪問內置插件

const config = {
    module: {
        rules: [
            { test: /\.txt$/, use: 'raw-loader' }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({template: './src/index.html'})
    ]
};

module.exports = config;
複製代碼

3.六、模式(mode)

經過選擇 development 或 production 之中的一個,來設置 mode 參數,你能夠啓用相應模式下的 webpack 內置的優化

module.exports = {
    mode: 'production'
};

webpack4容許咱們指定編譯使用開發模式仍是生產模式,這由mode這個配置來控制,value爲枚舉值:development/production,分別對應開發模式和生產模式(這個配置能夠做爲命令行的配置參數也能夠做爲配置文件中的一個配置項,默認值是production,即生產模式)。

源碼仍是不支持調試(都用eval函數包住),指定編譯時的source-map生成方式,默認值是eval,能夠解決問題。

3.七、代碼塊(Chunk)

一個 Chunk 由多個模塊組合而成,用於代碼合併與分割。

3.八、WebPack執行過程

Webpack 啓動後會從 Entry 裏配置的 Module 開始遞歸解析 Entry 依賴的全部 Module。 每找到一個 Module, 就會根據配置的 Loader 去找出對應的轉換規則,對 Module 進行轉換後,再解析出當前 Module 依賴的 Module。 這些模塊會以 Entry 爲單位進行分組,一個 Entry 和其全部依賴的 Module 被分到一個組也就是一個 Chunk。最後 Webpack 會把全部 Chunk 轉換成文件輸出。 在整個流程中 Webpack 會在恰當的時機執行 Plugin 裏定義的邏輯。

Webpack從入口(entry)開始工做,一般這些是JavaScript模塊,其中webpack開始其遍歷過程。在此過程當中,webpack會根據加載器配置評估入口(entry)匹配,這些配置告訴webpack如何轉換每一個匹配。

入口(entry)自己就是一個模塊。當webpack遇到一個入口時,webpack會嘗試使用入口的resolve配置將入口與文件系統匹配。除了node_modules以外,咱們還能夠告訴webpack對特定目錄執行查找。也能夠調整webpack與文件擴展名匹配的方式,而且能夠爲目錄定義特定的別名。該耗竭與包章涵蓋了更詳細的這些想法。

若是解析經過失敗,webpack會引起運行時錯誤。若是webpack設法正確解析文件,webpack將根據加載器定義對匹配的文件執行處理。每一個加載器對模塊內容應用特定的轉換。

能夠經過多種方式配置加載程序與已解析文件匹配的方式,包括文件類型和文件系統中的位置。Webpack的靈活性甚至容許咱們根據文件導入項目的位置對文件應用特定的轉換。

對webpack的加載器執行相同的解析過程。Webpack容許咱們在肯定應使用哪一個加載器時應用相似的邏輯。因爲這個緣由,裝載程序已經解析了本身的配置。若是webpack沒法執行加載程序查找,則會引起運行時錯誤。

在實際應用中你可能會遇到各類奇怪複雜的場景,不知道從哪開始。 根據以上總結,你會對 Webpack 有一個總體的認識,這能讓你在之後使用 Webpack 的過程當中快速知道應該經過配置什麼去完成你想要的功能,而不是無從下手。

 下圖能夠簡易的描述出webpack打包過程,該過程主要分爲三個階段:module構建、trunk構建和產出三個階段:

4、模塊轉換器Loader

loader 用於對模塊的源代碼進行轉換。loader 可使你在 import 或"加載"模塊時預處理文件。所以,loader 相似於其餘構建工具中「任務(task)」,並提供了處理前端構建步驟的強大方法。loader 能夠將文件從不一樣的語言(如 TypeScript)轉換爲 JavaScript,或將內聯圖像轉換爲 data URL。loader 甚至容許你直接在 JavaScript 模塊中 import CSS文件!

loader 是對應用程序中資源文件進行轉換。它們是(運行在 Node.js 中的)函數,能夠將資源文件做爲參數的來源,而後返回新的資源文件。

 

4.一、loader特性

loader 支持鏈式傳遞。可以對資源使用流水線(pipeline)。一組鏈式的 loader 將按照相反的順序執行。loader 鏈中的第一個 loader 返回值給下一個 loader。在最後一個 loader,返回 webpack 所預期的 JavaScript。

  • loader 能夠是同步的,也能夠是異步的。
  • loader 運行在 Node.js 中,而且可以執行任何可能的操做。
  • loader 接收查詢參數。用於對 loader 傳遞配置。
  • loader 也可以使用 options 對象進行配置。

除了使用 package.json 常見的 main 屬性,還能夠將普通的 npm 模塊導出爲 loader,作法是在 package.json 裏定義一個 loader 字段。

插件(plugin)能夠爲 loader 帶來更多特性。

loader 可以產生額外的任意文件。

loader 經過(loader)預處理函數,爲 JavaScript 生態系統提供了更多能力。 用戶如今能夠更加靈活地引入細粒度邏輯,例如壓縮、打包、語言翻譯和其餘更多。

loader 遵循標準的模塊解析。多數狀況下,loader 將從模塊路徑(一般將模塊路徑認爲是 npm install, node_modules)解析。

loader 模塊須要導出爲一個函數,而且使用 Node.js 兼容的 JavaScript 編寫。一般使用 npm 進行管理,可是也能夠將自定義 loader 做爲應用程序中的文件。按照約定,loader 一般被命名爲 xxx-loader(例如 json-loader)。

4.二、使用loader的三種方式

(1)、配置(推薦):在 webpack.config.js 文件中指定 loader

module.rules 容許你在 webpack 配置中指定多個 loader。 這是展現 loader 的一種簡明方式,而且有助於使代碼變得簡潔。同時讓你對各個 loader 有個全局概覽:

複製代碼
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          }
        ]
      }
    ]
  }
複製代碼

Loaders須要單獨安裝而且須要在webpack.config.js中的modules關鍵字下進行配置,Loaders的配置包括如下幾方面:

複製代碼
test:一個用以匹配loaders所處理文件的拓展名的正則表達式(必須)

loader:loader的名稱(必須)

include/exclude:手動添加必須處理的文件(文件夾)或屏蔽不須要處理的文件(文件夾)(可選)

query:爲loaders提供額外的設置選項(可選)
複製代碼

(2)、內聯:在每一個 import 語句中顯式指定 loader

能夠在 import 語句或任何等效於 "import" 的方式中指定 loader。使用 ! 將資源中的 loader 分開。分開的每一個部分都相對於當前目錄解析。

import Styles from 'style-loader!css-loader?modules!./styles.css';

經過前置全部規則及使用 !,能夠對應覆蓋到配置中的任意 loader。

選項能夠傳遞查詢參數,例如 ?key=value&foo=bar,或者一個 JSON 對象,例如 ?{"key":"value","foo":"bar"}。

儘量使用 module.rules,由於這樣能夠減小源碼中的代碼量,而且能夠在出錯時,更快地調試和定位 loader 中的問題。

(3)、CLI:在 shell 命令中指定它們

你也能夠經過 CLI 使用 loader:

webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'

這會對 .jade 文件使用 jade-loader,對 .css 文件使用 style-loader 和 css-loader。

4.三、常見的loader

4.3.一、文件

  • raw-loader 加載文件原始內容(utf-8)
  • val-loader 將代碼做爲模塊執行,並將 exports 轉爲 JS 代碼
  • url-loader 像 file loader 同樣工做,但若是文件小於限制,能夠返回 data URL
  • file-loader 將文件發送到輸出文件夾,並返回(相對)URL

4.3.二、JSON

4.3.三、轉換編譯(Transpiling)

4.3.四、模板(Templating)

  • html-loader 導出 HTML 爲字符串,須要引用靜態資源
  • pug-loader 加載 Pug 模板並返回一個函數
  • jade-loader 加載 Jade 模板並返回一個函數
  • markdown-loader 將 Markdown 轉譯爲 HTML
  • react-markdown-loader 使用 markdown-parse parser(解析器) 將 Markdown 編譯爲 React 組件
  • posthtml-loader 使用 PostHTML 加載並轉換 HTML 文件
  • handlebars-loader 將 Handlebars 轉移爲 HTML
  • markup-inline-loader 將內聯的 SVG/MathML 文件轉換爲 HTML。在應用於圖標字體,或將 CSS 動畫應用於 SVG 時很是有用。

4.3.五、樣式

  • style-loader 將模塊的導出做爲樣式添加到 DOM 中
  • css-loader 解析 CSS 文件後,使用 import 加載,而且返回 CSS 代碼
  • less-loader 加載和轉譯 LESS 文件
  • sass-loader 加載和轉譯 SASS/SCSS 文件
  • postcss-loader 使用 PostCSS 加載和轉譯 CSS/SSS 文件
  • stylus-loader 加載和轉譯 Stylus 文件

4.3.六、清理和測試(Linting && Testing)

4.3.七、框架(Frameworks)

  • vue-loader 加載和轉譯 Vue 組件
  • polymer-loader 使用選擇預處理器(preprocessor)處理,而且 require() 相似一等模塊(first-class)的 Web 組件
  • angular2-template-loader 加載和轉譯 Angular 組件

4.四、raw-loader(文件原始內容轉換器)

一個能夠用於加載文件做爲字符串使用的加載器,使用UTF-8編碼。

安裝

npm i --D raw-loader

 安裝結果:

用法一:

經過 webpack 配置、命令行或者內聯使用 loader。

複製代碼
webpack.config.js

module.exports = { module: { rules: [ { test: /\.txt$/, use: 'raw-loader' } ] } }
複製代碼

在你的項目中

import txt from './file.txt';

用法二:經過命令行(CLI)

webpack --module-bind 'txt=raw-loader'

用法三:在你的項目中

import txt from 'file.txt';

內聯使用

import txt from 'raw-loader!./file.txt';

示例:

webpack.config.json

  View Code

src/file1.txt

A loader for webpack that lets you import files as a string.

src/bar.js

複製代碼
//定義模塊
//部分依賴lodash中的join方法
import {join} from 'lodash';
//導入模塊,得到file1.txt中的文件內容,被raw-loader處理
import message from './file1.txt';

//導出一個默認模塊
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join鏈接數組將結果寫入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ')+"<br/>"+message;
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
複製代碼

運行結果:

內聯使用模塊處理器:

4.五、CSS Loader(樣式處理)

webpack提供兩個工具處理樣式表,css-loader 和 style-loader,兩者處理的任務不一樣,css-loader使你可以使用相似@import 和 url(...)的方法實現 require()的功能,style-loader將全部的計算後的樣式加入頁面中,兩者組合在一塊兒使你可以把樣式表嵌入webpack打包後的JS文件中。

  • css-loader: 加載.css文件
  • style-loader:使用<style>將css-loader內部樣式注入到咱們的HTML頁面

css-loader詳解:

https://www.npmjs.com/package/css-loader

https://www.webpackjs.com/loaders/css-loader/

style-loader詳解:

https://www.npmjs.com/package/style-loader

https://www.webpackjs.com/loaders/style-loader/

4.5.一、安裝

//安裝
npm i style-loader css-loader -D

4.5.二、配置

複製代碼
const path = require("path");

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: "bundle.js"
    },
    module: {
        rules: [
            {
                test:/\.css/,
                use:['style-loader',{
                    loader: 'css-loader',
                    options: {
                        sourceMap:true
                    }
                }]
            }
        ]
    },
    mode: "development"
};
複製代碼

4.5.三、定義樣式與引用

base.css

複製代碼
h2{
    height: 40px;
    line-height: 40px;
    background: crimson;
    color:#fff;
}
複製代碼

bar.js

複製代碼
import {join} from 'lodash';
import base from '../css/base.css';

export default function bar() {
    function component() {
        var element=document.createElement("h2");
        element.innerHTML=join(['Hello','Webpack!']);
        return element;
    }
    document.body.appendChild(component());
}
複製代碼

4.5.四、打包運行

打包:

運行:

生成代碼:

4.5.五、注意事項

  1. rules裏的數據類型爲對象,每個loader都是一個對象
  2. test表示loader要處理什麼類型的文件,這裏用了一個正則去匹配文件類型
  3. use表示要使用哪一個loader,它的值是個數組,loader的使用順序是從後往前
  4. 這個loader的意思爲,在入口文件裏找到.css類型的文件,先拿css-loader去處理成瀏覽器認識的css,再拿style-loader把處理後的css放在頁面的style標籤裏

4.六、sass-loader(加載和轉譯 SASS/SCSS 文件)

加載sass或scss文件並轉譯成css

用css-loader或raw-loader 轉換成一個JS模塊或用ExtractTextPlugin插件將樣式分隔成一個單獨文件。

安裝

npm i sass-loader node-sass --D

 

node-sass 和 webpack 是 sass-loader 的 peerDependency,所以可以精確控制它們的版本。

示例

css/baseScss.scss

複製代碼
$height:50px;
$color:#3366ff;

h2{
  background: $color;
  height: $height;
  line-height: $height;
  color: white;
  padding-left: $height/5;
}
複製代碼

 

經過將 style-loader 和 css-loader 與 sass-loader 鏈式調用,能夠馬上將樣式做用在 DOM 元素。

配置webpack.config.json

複製代碼
//webpack配置文件

//依賴node中的path模塊
var path=require('path');

//定義一個默認模塊對象
module.exports={
    //指定入口文件的位置,多入口
    entry:{
        index:"./src/index.js",
        main:"./src/main.js"
    },
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模塊名稱,佔位
        filename: "[name].bundle.js"
    },
    module: {  //模塊處理
        rules: [ //處理器
            {
                test:/\.txt$/,  //當模塊的後綴爲.txt時匹配
                use: "raw-loader"  //模塊轉換器,能夠以對象的形式指定參數
            },
            {
                test:/\.css$/,  //匹配全部css模塊
                //use表示要使用哪一個loader,它的值是個數組,loader的使用順序是從後往前
                use: ["style-loader",{
                    loader: "css-loader",  //轉換器名稱
                    options: {  //配置選項
                        modules:true,  //模塊化
                        sourceMap:true  //是否生成調試文件
                    }
                }]  //使用多個模塊轉換器
            },
            {
                test: /\.scss$/,
                use: [{
                    loader: "style-loader" // 將 JS 字符串生成爲 style 節點
                }, {
                    loader: "css-loader" // 將 CSS 轉化成 CommonJS 模塊
                }, {
                    loader: "sass-loader" // 將 Scss 編譯成 CSS
                }]
            }
        ]
    },
    mode: "development"
};
複製代碼

 

導入scss做爲模塊

複製代碼
//定義模塊
//部分依賴lodash中的join方法
import {join} from 'lodash';
//導入模塊,得到file1.txt中的文件內容,被raw-loader處理
import message from './file1.txt';
//導入樣式文件
//import '../css/baseCss.css' //導入預處理樣式文件
import '../css/baseScss.scss'

//導出一個默認模塊
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join鏈接數組將結果寫入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ')+"<br/>"+message;
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
複製代碼

打包後運行結果:

一般,生產環境下比較推薦的作法是,使用 ExtractTextPlugin 將樣式表抽離成專門的單獨文件。這樣,樣式表將再也不依賴於 JavaScript:

複製代碼
const ExtractTextPlugin = require("extract-text-webpack-plugin");

const extractSass = new ExtractTextPlugin({
    filename: "[name].[contenthash].css",
    disable: process.env.NODE_ENV === "development"
});

module.exports = {
    ...
        module
:
{
    rules: [{
        test: /\.scss$/,
        use: extractSass.extract({
            use: [{
                loader: "css-loader"
            }, {
                loader: "sass-loader"
            }],
// 在開發環境使用 style-loader
            fallback: "style-loader"
        })
    }]
}
,
plugins: [
    extractSass
]
}
;
複製代碼

4.七、url-loader(路徑處理器)

 Webpack 容許你在js文件中require圖片 , 經過 url-loader和file-loader來預處理圖片文件,將圖片轉換成base64編碼。

安裝

npm install --save-dev url-loader file-loader

用法

url-loader 功能相似於 file-loader,可是在文件大小(單位 byte)低於指定的限制時,能夠返回一個 DataURL。

import img from './image.png'

配置

複製代碼
webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192
                        }
                    }
                ]
            }
        ]
    }
}
複製代碼

示例

webpack.config.js

複製代碼
//webpack配置文件

//依賴node中的path模塊
var path=require('path');

//定義一個默認模塊對象
module.exports={
    entry:{app01:"./src/app01.js"},
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模塊名稱,佔位
        filename: "[name].bundle.js"
    },
    module: {
        rules: [
            {
                //如是文件名是gif,jpg,jpeg,bmp圖片則匹配,不分大小寫
                test:/\.(gif|jpe?g|png|bmp)/i,
                use: {
                    loader: "url-loader",
                    options: {
                        //若是圖片的大小小於1024byte(B)時轉換成dataUrl,base64編碼
                        limit:1024,
                        fallback:"responsive-loader"
                    }
                }
            }
        ]
    }
};
複製代碼

src/app01.js

複製代碼
//導入大圖片 404byte
import srcBig from '../img/big.jpg';
//導入小圖片 100Kbyte
import srcSma from '../img/small.gif';

console.log(srcBig);
console.log(srcSma)

alert("Hello App01!");

//建立大圖片DOM
var img1=document.createElement("img");
//指定url
img1.src=srcBig;
//添加到文檔中
document.body.appendChild(img1);

//建立小圖片DOM
var img2=document.createElement("img");
//指定url
img2.src=srcSma;
//添加到文檔中
document.body.appendChild(img2);
複製代碼

運行結果:

5、插件plugins

5.一、插件概要

Plugin 是用來擴展 Webpack 功能的,經過在構建流程裏注入鉤子實現,它給 Webpack 帶來了很大的靈活性。

插件是 webpack 的支柱功能。webpack 自身也是構建於,你在 webpack 配置中用到的相同的插件系統之上!插件目的在於解決 loader 沒法實現的其餘事。

webpack 插件是一個具備 apply 屬性的 JavaScript 對象。apply 屬性會被 webpack compiler 調用,而且 compiler 對象可在整個編譯生命週期訪問。

複製代碼
ConsoleLogOnBuildWebpackPlugin.js

const pluginName = 'ConsoleLogOnBuildWebpackPlugin';

class ConsoleLogOnBuildWebpackPlugin {
    apply(compiler) {
        compiler.hooks.run.tap(pluginName, compilation => {
            console.log("webpack 構建過程開始!");
        });
    }
}
複製代碼

 

compiler hook 的 tap 方法的第一個參數,應該是駝峯式命名的插件名稱。建議爲此使用一個常量,以便它能夠在全部 hook 中複用。

因爲插件能夠帶參數/選項,你必須在 webpack 配置中,向 plugins 屬性傳入 new 實例。

根據你的 webpack 用法,這裏有多種方式使用插件。

複製代碼
webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); //經過 npm 安裝
const webpack = require('webpack'); //訪問內置的插件
const path = require('path');

const config = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader'
      }
    ]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

module.exports = config;
複製代碼

5.一、HTML Webpack Plugin(建立HTML插件)

該個插件的做用是用來自動生成html頁面,既能夠生成單個頁面又能夠生成多個頁面,而且在生成前能夠給它一些的配置參數,它會按照你想要的生成方式去生成頁面。

第一步:安裝

npm i html-webpack-plugin -D

第二步:在webpack.config.js裏引入模塊

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

第三步:在webpack.config.js中的plugins對象裏new一個實例

plugins:[
  new HtmlWebpackPlugin({參數})
]

結果

複製代碼
const HtmlWebpackPlugin = require('html-webpack-plugin')
 
module.exports = {
  entry: 'index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin()
  ]
}
複製代碼

參數:

title

生成頁面的titile元素

filename

生成的html文件的文件名。默認index.html,能夠直接配置帶有子目錄

複製代碼
//webpack.config.js
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    filename: 'index1.html'//可帶子目錄'html/index1.html'
  })
]
複製代碼

template

模版文件路徑

templateParameters

{Boolean|Object|Function} 容許覆蓋模板中使用的參數

複製代碼
//webpack.config.js
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    templateParameters: {
      title: 'xxxx',
      favicon: './favicon/index.ico',
    }
  })
]
複製代碼

inject

插入的script插入的位置,四個可選值:
true: 默認值,script標籤位於html文件的body底部
body: 同true
headscript標籤位於html文件的head標籤內
false: 不插入生成的js文件,只是生成的html文件

favicon

爲生成的html文件生成一個favicon,屬性值是路徑

minify

html文件進行壓縮。屬性值是false或者壓縮選項值。默認false不對html文件進行壓縮。
html-webpack-plugin中集成的html-minifier,生成模板文件壓縮配置,有不少配置項,這些配置項就是minify的壓縮選項值。

hash

給生成的js文件尾部添加一個hash值。這個hash值是本次webpack編譯的hash值。默認false;

複製代碼
//webpack.config.js
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    hash: true
  })
]
//html
<script type="text/javascript" src="bundle.js?59a5ed17040d94df87fe">
//59a5ed17040d94df87fe是本次webpack編譯的hash值
複製代碼

cache

Boolean類型。只在文件被修改的時候才生成一個新文件。默認值true

showErrors

Boolean類型。錯誤信息是否寫入html文件。默認true

chunks

html文件中引用哪些js文件,用於多入口文件時。不指定chunks時,全部文件都引用

複製代碼
//webpack.config.js
entry: {
  index1: path.resolve(__dirname, './index1.js'),
  index2: path.resolve(__dirname, './index2.js'),
  index3: path.resolve(__dirname, './index3.js')
}
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    chunks: [index1, index2]//html文件中只引入index1.js, index2.js
  })
]
複製代碼

 

excludeChunks

與chunks相反,html文件不引用哪些js文件

複製代碼
//webpack.config.js
entry: {
  index1: path.resolve(__dirname, './index1.js'),
  index2: path.resolve(__dirname, './index2.js'),
  index3: path.resolve(__dirname, './index3.js')
}
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    excludeChunks: [index3.js]//html文件中不引入index3.js
  })
]
複製代碼

 

chunksSortMode

控制script標籤的引用順序。默認五個選項:
none: 無序
auto: 默認值, 按插件內置的排序方式
dependency: 根據不一樣文件的依賴關係排序
manual: chunks按引入的順序排序, 即屬性chunks的順序
{Function}: 指定具體的排序規則

xhtml

Boolean類型,默認falsetrue時以兼容xhtml的模式引用文件

示例:

複製代碼
plugins:[
    new HtmlWebpackPlugin({
        title:'Hello app',    /*這個值對應html裏的title*/
        template:'./src/template.html', //模板文件地址
        filename:'test1.html',  //文件名,默認爲index.html(路徑相對於output.path的值)
        inject:true,    //script標籤的位置,true/body爲在</body>標籤前,head爲在<head>裏,false表示頁面不引入js文件
        hash:true,  //是否爲引入的js文件添加hash值
        chunks:['one'], //頁面裏要引入的js文件,值對應的是entry裏的key。省略參數會把entry裏全部文件都引入
        //excludeChunks:['one'],//頁面裏不能引入的js文件,與chunks恰好相反
        minify:{    //html-webpack-plugin內部集成了html-minifier
            collapseWhitespace:true,    //壓縮空格
            removeAttributeQuotes:true, //移除引號
            removeComments:true,        //移除註釋
        },
    }),
    //生成兩個文件,分別引入兩個js文件(如今是一個文件裏引入了兩個js)
    new HtmlWebpackPlugin({
        title:'kaivon',
        template:'./src/template.html',
        hash:true,
        filename:'test2.html',
        chunks:['two']
    })
]
複製代碼

示例1:

webpack.config03.js配置文件

複製代碼
//webpack配置文件

//導入用於生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin");

//依賴node中的path模塊
var path=require('path');

//定義一個默認模塊對象
module.exports={
    entry:{app01:"./src/app03.js"},
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模塊名稱,佔位
        filename: "[hash:8].bundle.js"
    },
    module: {
    },
    plugins: [
        //建立一個插件對象,並指定參數
        new HtmlWebpackPlugin({
            //指定生成的文件路徑與名稱
            filename:"../app03.html",
            //標題
            title:"Hello App03!"
        })
    ]
};
複製代碼

arc/app03.js

alert("Hello App03!");

打包結果:

運行:

示例2:

webpack.config03.js配置文件

複製代碼
//webpack配置文件

//導入用於生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin");

//依賴node中的path模塊
var path=require('path');

//定義一個默認模塊對象
module.exports={
    entry:{app01:"./src/app03.js"},
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模塊名稱,佔位
        filename: "[hash:8].bundle.js"
    },
    module: {
    },
    plugins: [
        //建立一個插件對象,並指定參數
        new HtmlWebpackPlugin({
            //指定生成的文件路徑與名稱
            filename:"../app03.html",
            //標題
            title:"Hello App03!",
            //指定模板
            template:"./templates/tmpl03.html",
            //模板參數,容許覆蓋templates中的參數
            templateParameters:{
                content:"Hello templateParameters!",
                //重寫title
                title:"Hello App03 title!",
                key:"value"
            },
            minify:{
                removeComments:true,  //移除註釋
                collapseWhitespace:true,  //摺疊空格
                //更新請參數https://github.com/kangax/html-minifier#options-quick-reference
            }
        })
    ]
};
複製代碼

/templates/tmpl03.html 模板文件

  View Code

生成結果:

5.二、Mini-css-extract-plugin(單獨提取CSS插件)

將CSS提取爲獨立的文件的插件,對每一個包含css的js文件都會建立一個CSS文件,支持按需加載css和sourceMap

默認狀況下css是被js注入的一段style,以下所示:

只能用在webpack4中,對比另外一個插件 extract-text-webpack-plugin特色:

  • 異步加載
  • 不重複編譯,性能更好
  • 更容易使用
  • 只針對CSS

目前缺失功能,HMR(熱模塊替換)。

  HMR解釋

安裝:

npm install --save-dev mini-css-extract-plugin

使用:

複製代碼
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // 相似 webpackOptions.output裏面的配置 能夠忽略
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              // 這裏能夠指定一個 publicPath
              // 默認使用 webpackOptions.output中的publicPath
              publicPath: '../'
            },
          },
          'css-loader',
        ],
      }
    ]
  }
}
複製代碼

高級配置:

這個插件應該只用在 production 配置中,而且在loaders鏈中不使用 style-loader, 特別是在開發中使用HMR,由於這個插件暫時不支持HMR

複製代碼
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: devMode ? '[name].css' : '[name].[hash].css',
      chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
    })
  ],
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader',
        ],
      }
    ]
  }
}
複製代碼

示例:

webpack.config03.js

複製代碼
//webpack配置文件

//導入用於生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin");
//導入用於提取css的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

//依賴node中的path模塊
var path=require('path');

//定義一個默認模塊對象
module.exports={
    entry:{app01:"./src/app03.js"},
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模塊名稱,佔位
        filename: "[hash:8].bundle.js"
    },
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [{
                    loader:MiniCssExtractPlugin.loader //提取css並link
                }, {
                    loader: "css-loader" // 將 CSS 轉化成 CommonJS 模塊
                }, {
                    loader: "sass-loader" // 將 Scss 編譯成 CSS
                }]
            }
        ]
    },
    plugins: [
        //建立一個插件對象,並指定參數
        new HtmlWebpackPlugin({
            //指定生成的文件路徑與名稱
            filename:"../app03.html",
            //標題
            title:"Hello App03!",
            //指定模板
            template:"./templates/tmpl03.html",
            //模板參數,容許覆蓋templates中的參數
            templateParameters:{
                content:"Hello templateParameters!",
                //重寫title
                title:"Hello App03 title!",
                key:"value"
            },
            minify:{
                removeComments:true,  //移除註釋
                collapseWhitespace:true,  //摺疊空格
                //更新請參數https://github.com/kangax/html-minifier#options-quick-reference
            }
        }),
        //建立一個用於提取css的插件對象
        new MiniCssExtractPlugin({
            filename:"[name]_[hash:10].css",
            chunkFilename:"[id]"
        })
    ]
};
複製代碼

src/app03.js

import '../css/baseScss.scss';

alert("Hello App03!");

打包生成的結果

複製代碼
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>Hello App03 title!</title>
    <link href="dist/app01_1b7c11aa92.css" rel="stylesheet">
</head>
<body><h2>Hello templateParameters!</h2>
<script type="text/javascript" src="dist/1b7c11aa.bundle.js"></script>
</body>
</html>
複製代碼

運行結果:

5.三、clean-webpack-plugin(刪除或清理構建目錄)

在用HtmlWebpackPlugin的時候時須要把dist目錄刪掉再去看生成的文件,clean-webpack-plugin這個插件就能夠作這件事情

第一步:安裝

npm i clean-webpack-plugin --save-dev

 

第二步:在webpack.config.js裏引入模塊

const CleanWebpackPlugin=require('clean-webpack-plugin');

 

第三步:在plugins的最前面建立清理對象

複製代碼
plugins:[
new CleanWebpackPlugin(['./dist']), //這個必定要放在最上面,做用是先刪除dist目錄再建立新的dist目錄。裏面的參數爲要刪除的目錄,放在一個數組裏面
...
]
複製代碼

 

在文件夾裏打開dist所在的目錄,並在終端裏再次執行命令webpack後,會看到dist目錄先被刪除後又被建立。

關於clean-webpack-plugin插件的全部配置參數請參考:https://www.npmjs.com/package/clean-webpack-plugin

示例:

複製代碼
const CleanWebpackPlugin = require('clean-webpack-plugin'); //installed via npm
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
const path = require('path');
 
// the path(s) that should be cleaned
let pathsToClean = [
  'dist',
  'build'
]
 
// the clean options to use
let cleanOptions = {
  root:     '/full/webpack/root/path',
  exclude:  ['shared.js'],
  verbose:  true,
  dry:      false
}
 
// sample WebPack config
const webpackConfig = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        loader: 'babel-loader'
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(pathsToClean, cleanOptions),
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
}
複製代碼

6、DevServer開發服務器 

在實際開發中咱們可能會須要完成以下功能:

  1. 提供 HTTP 服務而不是使用本地文件預覽;
  2. 監聽文件的變化並自動刷新網頁,作到實時預覽;
  3. 支持 Source Map,以方便調試。

Webpack 原生支持上述第二、3點內容,再結合官方提供的開發工具 DevServer 也能夠很方便地作到第1點。 DevServer 會啓動一個 HTTP 服務器用於服務網頁請求,同時會幫助啓動 Webpack ,並接收 Webpack 發出的文件更變信號,經過 WebSocket 協議自動刷新網頁作到實時預覽。

6.一、快速開啓DevServer

安裝 DevServer:

npm i -D webpack-dev-server

安裝成功後在項目的根目錄下執行webpack-dev-server 命令, DevServer 服務器就啓動了,這時你會看到控制檯有一串日誌輸出:

Project is running at http://localhost:8080/

webpack output is served from /

如今就能夠直接訪問了

這意味着 DevServer 啓動的 HTTP 服務器監聽在 http://localhost:8080/ ,DevServer 啓動後會一直駐留在後臺保持運行,訪問這個網址你就能獲取項目根目錄下的 index.html。 

相關文章
相關標籤/搜索