webpack


1、什么是webpack

Webpack是前端一個工具,可以讓各個模塊進行加載,預處理,再進行打包。現代的前端開發很多環境都依賴webpack構建,比如vue官方就推薦使用webpack。

2、簡單使用下webpack

2.1、首先我在 c 盤下新建一個webpack-demo1的文件夾,然后命令行進入該目錄,執行 npm init --yes 項目初始化,該命令會在文件下生成一個package.json文件,該命令也可以是 npm init ,這樣的話它會詢問你一系列諸如項目名稱,項目描述,作者等信息,如果你不准備在npm中發布你的模塊,這些問題的答案都不重要,一路回車默認即可。package.json如下:

{
  "name": "webpack-demo1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

接下來在該環境中安裝一下3.5.6版本webpack,命令 npm install webpack@3.5.6 --save-dev,接下來再全局安裝一下,npm install webpack@3.5.6 -g,安裝成功之后,package.json文件會出現webpack的版本信息:

{
  "name": "webpack-demo1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^3.5.6"
  }
}

 

實現打包功能:

打包一個js文件

在根目錄下新建一個index.js,和index.html文件,index.js文件內容:

function say(){
    alert("hello webpack");
}
say();

輸入命令:webpack index.js index.bundle.js,該命令含義:

#webpack {entry file} {destination for bundled file}

# {extry file}出填寫入口文件的路徑,本文中就是上述main.js的路徑,

# {destination for bundled file}處填寫打包文件的存放路徑

# 填寫路徑的時候不用添加{}

結果自動生成了一個 index.bundle.js 的文件,我們可以在index.html中引入,在瀏覽器中順利彈出 “hello webpack”

打包多個文件:

在根目錄下又新建一個calc.js文件,內容:

function add(a,b){
    return a+b;
}
module.exports = {    //導出這個模塊
    add: add
}

把index.js文件內容更改:

var oCalc = require("./calc");   //引入模塊
function say(){
    alert("hello webpack");
}
say();
alert(oCalc.add(10,20));    //使用該模塊的功能

執行打包:webpack index.js index.bundle.js,成功后,打開index.html,彈出倆次 1、“hello webpack”   2、“30”

webpack打包,后面可以跟很多參數:

  • --progress: 打包進度
  • --display-modules: 打包的模塊
  • --colors: 是否彩色顯示 打包提示信息
  • --display-reasons: 打包原因
  • --watch: 自動監控文件變化

比如我使用 --watch:webpack index.js index.bundle.js --watch,這樣的話會自動監測,只要與index.js相關的文件發生了變化,自動打包。

 

webpack.config.js

Webpack擁有很多其它的比較高級的功能(比如說本文后面會介紹的loadersplugins),這些功能其實都可以通過命令行模式實現,但是正如前面提到的,這樣不太方便且容易出錯的,更好的辦法是定義一個配置文件,這個配置文件其實也是一個簡單的JavaScript模塊,我們可以把所有的與打包相關的信息放在里面。演示,新建一個基本目錄結構webpack-demo2如圖:

其中main.js文件隨便寫一些內容:

function say(){
    alert("今天是星期五");
}
say();

接下來,配置一下webpack.config.js文件:

module.exports = {
    entry: "./src/js/main.js",
    output: {
        path: __dirname + "/dist/",
        filename: "js/index.bundle.js"
    }      
}    

這里參數做一下解釋,entry就是入口,項目被運行時,第一個被查找的文件,output就是出口,path是輸出路徑,要使用絕對路徑,__dirname是當前文件的絕對路徑,“E:\webpack-demo2\src\js”,filename是輸出文件的文件名,可以在前面加上路徑,稍后它會自動生成該路徑,配置好之后,進行打包,命令行:webpack(這里不用再寫后面的倆個參數了,因為我們已經在webpack.config.js里已經配置好了),成功后依照我們配置好的路徑,在dist/js目錄下,生成了index.bundle.js文件

在index.html中引入該文件,然后運行,順利彈出“今天是星期五”

 

我們還可以通過package.json文件的scripts部分,簡化打包操作:

比如我們進行打包時后面跟着的幾個參數(上面有說),我們可以在package.json里配置下:

"dev" : "webpack --config webpack.dev.config.js --progress --display-modules --colors --display-reasons"

這樣的話我們在執行打包時直接命令:npm run dev 就會執行相應的打包,后面幾個參數也會生效。簡化了操作。

 

我們上面是打包一個js文件,如果想打包多個文件呢,這里有倆種情況:

1、多個文件打包成一個文件,這里要用數組配置entry了,比如,我們在main.js同目錄下新建一個calc.js文件,內容:

function add(a,b) {
    alert(a + b);
}
add(10,20);

把webpack.config.js文件內容更新為:

module.exports = {
    entry: ["./src/js/main.js","./src/js/calc.js"],   //entry用數組配置
    output: {
        path: __dirname + "/dist/",
        filename: "js/index.bundle.js"
    }
}

執行打包后成功將倆個文件打包在dist/js.index.bundle.js,預覽index.js,彈出倆次 “今天是星期五” “30”

2、多個文件打包成多個文件,這里entry要采用字面量(json)方式配置

 

module.exports = {
    entry: {
        main: "./src/js/main.js",
        calc: "./src/js/calc.js"
    },
    output: {
        path: __dirname + "/dist/",
        filename: "js/[name].bundle.js"   //filename支持多種動態起名字的方式( id, name, hash, chunkhash, query ) name就是entry里寫的文件的名字
    }
}

執行打包,成功在dist/js里生成倆個文件

 

html-webpack-plugin插件的使用

我們打包后的js文件,默認不會自動插入到模板文件中的,我們可以安裝html-webpack-plugin插件,先安裝這個插件 npm install html-webpack-plugin --save-dev,接下來在webpack.config.js中引入並配置一下:

var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry: {
        main: "./src/js/main.js",
        calc: "./src/js/calc.js"
    },
    output: {
        path: __dirname + "/dist/",
        filename: "js/[name].bundle.js"   //filename支持多種動態起名字的方式( id, name, hash, chunkhash, query ) name就是entry里寫的文件的名字
    },
    plugins: [new HtmlWebpackPlugin()]
}

弄好之后,執行打包,與之前不同的是這次直接在dist目錄下生成了index.html文件,該html文件自動引入了打包后的倆個js文件。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Webpack App</title>
  </head>
  <body>
  <script type="text/javascript" src="js/main.bundle.js"></script><script type="text/javascript" src="js/calc.bundle.js"></script></body>
</html>

但是有一個問題,我們在根目錄下本來就建好了一個html文件,這次重新生成的文件和之前的沒有任何的聯系,我們需要讓生成的html文件內容參照原有html文件。重新配置下webpack.config.js。

 plugins: [new HtmlWebpackPlugin( { template : './index.html' } )]

這次打包的話,就是參照原模板html文件,進行生成了。並自動引入了js文件。

插件的其他配置選項:

filename:打包生成的文件名,還可以加目錄,默認沒有寫的時候是index.html

inject:有4個值:

  •  true  引入js文件
  • 'head'   把js引入放在head標簽里面
  • 'body'   把js引入放在body標簽里面
  • false   不引入js文件

舉栗:重新配置下webpack.config.js文件中的plugins:

plugins: [new HtmlWebpackPlugin(
     {
        template : './index.html',
         filename : 'index-bundle.html',
         inject : 'head'
     }
 )]

然后打包,這次在dist目錄下生成的html文件名為index.bundle.html,並且自動引入的js文件在head標簽內。

插件的另一個選項title,就是設置一個標題,用法如下,webpack.config.js文件中的plugins:

plugins: [new HtmlWebpackPlugin(
        {
            template : './index.html',
            filename : 'index-bundle.html',
            inject : 'head',
            title: 'hello webpack~'
        }
)]

 接下來在原html文件中的title標簽內寫入:

<title><%= htmlWebpackPlugin.options.title %></title>

現在打包后的html文件的標題為 “hello webpack~”

html-webpack-plugin插件中的options除了自己定義了一些基本配置外,我們是可以任意的添加自定義的數據:

plugins: [
    new HtmlWebpackPlugin({
        template : './index.html',
        title : 'hello webpack',
        inject : true,
        date : new Date(),
        userName : '張三',
        age : 22
    })
]

在原始模板html文件中讀取:

<h3><%= htmlWebpackPlugin.options.date %></h3>
<h3><%= htmlWebpackPlugin.options.userName %></h3>
<h3><%= htmlWebpackPlugin.options.age %></h3>

這樣的話,在生成的html文件中就會添加相應的數據。

 

minify選項,壓縮html文件:

new HtmlWebpackPlugin({
     template : './index.html',
     title : 'ghostwu教你學webpack',
     inject : false,
     minify : {
         removeComments : true, //去掉注釋
         collapseWhitespace : true, //去掉空行
     }
 })

再次打包,這次html文件都被壓縮。

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body>我是原有的模板文件~</body></html>

 

chunks選項

這個屬性非常有用,可以指定某個頁面加載哪些chunk( 可以簡單的把他理解成js文件 ),我們可以用他做多個頁面模板的生成. 比如,我們在實際開發中,做一個博客網站,一般來說有首頁,文章列表頁,文章詳情頁等等,這些頁面都有一個特點,都要引入一些公共的js文件以及該頁面特有的js文件,比如:

  • 首頁( index.html )                  引入 main.js, index.js
  • 文章列表頁( list.html )           引入 main.js, list.js
  • 文章詳情頁( detail.html )       引入 main.js, detail.js

傳統方式,一個個的打開文件,拷貝修改,如果后期維護,又是一堆文件中,查找,拷貝,修改。很容易出錯,而且效率低下,可以用webpack解決,

我們先在src/js中創建對應js,然后webpack.config.js配置:

var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry : {
        main : './src/js/main.js',
        index : './src/js/index.js',
        list : './src/js/list.js',
        detail : './src/js/detail.js'
    },
    output : {
        //__dirname,就是當前webpack.config.js文件所在的絕對路徑
        path : __dirname + '/dist', //輸出路徑,要用絕對路徑
        filename : 'js/[name].bundle.js', //打包之后輸出的文件名
    },
    plugins: [
        new HtmlWebpackPlugin({
            template : './index.html',
            title : '博客首頁-',
            filename : 'index.html',
            inject : true,
            chunks : ['main', 'index']
        }),
        new HtmlWebpackPlugin({
            template : './index.html',
            title : '列表頁-',
            filename : 'list.html',
            inject : true,
            chunks : ['main', 'list']
        }),
        new HtmlWebpackPlugin({
            template : './index.html',
            title : '文章詳情頁-',
            filename : 'detail.html',
            inject : true,
            chunks : ['main', 'detail']
        })
    ]
};

執行打包,成功之后,會在dist目錄下生成3個html文件,並且在引入main.js的同時,各自引入屬於自己的js。

 

loader 

官方解釋為文件的預處理器,通俗點說webpack在處理靜態資源的時候,需要加載各種loader,比如,html文件,要用html-loader,要讓js識別css文件要用css-loader,讓文件在頁面中生效要用style-loader等等.

babel-loader的作用---打包時把es6語法轉為瀏覽器認識的es5語法,用法:

先建一個webpack-demo3的基本機構

需要安裝的插件等:
1,npm init --yes( 初始化項目的package.json )
2,npm install webpack@3.5.6 -g ( 全局安裝webapck )
3,npm install webpack@3.5.6 --save-dev (局部安裝webpack )
4,npm install html-webpack-plugin --save-dev ( 安裝html-webpack-plugin插件 )

webpack.config.js文件:

var htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry : './src/main.js',
    output : {
        path : __dirname + '/dist',
        filename : 'js/[name].bundle.js',
    },
    plugins : [
        new htmlWebpackPlugin({
            filename : 'index.html',
            template : 'index.html',
            inject : true
        })
    ]
}

 

modal.js文件

let modal = function(){
    return {
        'component-name' : 'modal'
    }
}
export default modal;

 

main.js文件

import modal from './components/modal.js';
let App = function(){
    console.log( '項目入口文件main.js' );
}
new App();

進行打包,然后查看dist/js/下的main.bundle.js文件,發現是引入了es6的語法,這樣的話瀏覽器是不認識的,我們可以在打包之前用babel.loader解決。

安裝babel-loader:npm install --save-dev babel-loader babel-core babel-preset-env webpack

配置一下babel-loader:

var htmlWebpackPlugin = require('html-webpack-plugin');
let path = require('path');
module.exports = {
    entry: './src/main.js',
    output: {
        path: __dirname + '/dist',
        filename: 'js/[name].bundle.js',
    },
    plugins: [
        new htmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html',
            inject: true
        })
    ],
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /(node_modules)/,
                include: [
                    path.resolve(__dirname, "src"),
                ],
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['env']
                    }
                }
            }
        ]
    }
}

rules就是配置規則,他是一個數組,每一項為一個對象,如果有多個loader,那就用多個對象,

test: /\.js$/ 就是以.js結尾的文件,exclude:排除node_modules這個目錄,意思就是不要去這個目錄下處理.js的文件,有什么好處呢?大大提高打包的速度. include里面的配置意思就是把src目錄下面的js文件作為處理的目標,

use配置就是使用babel-loader

再進行打包,成功之后查看打包后生成的main.bundle.js文件中,發現已經轉成es5語法了。

var App = function App() {
    console.log('項目入口文件main.js');
};
new App();

css-loader style-loader

在src目錄下建一個css目錄,里面有一個sytle.css文件,

body{
    background-color: bisque;
}

在main.js中導入css文件

import modal from './components/modal.js';
import './css/style.css';
let App = function(){
    console.log( '項目入口文件main.js' );
}
new App();

執行打包,會報錯 “你可能需要一個loader來處理這個文件類型”,我們可以安裝對應loader解決,npm install css-loader style-loader --save-dev,安裝完之后,配置一下webpack.config.js:

var htmlWebpackPlugin = require('html-webpack-plugin');
let path = require('path');
module.exports = {
    entry: './src/main.js',
    output: {
        path: __dirname + '/dist',
        filename: 'js/[name].bundle.js',
    },
    plugins: [
        new htmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html',
            inject: true
        })
    ],
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /(node_modules)/,
                include: [
                    path.resolve(__dirname, "src"),
                ],
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['env']
                    }
                }
            },
            {
                test: /\.css$/,
                exclude: /(node_modules)/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }
}
執行webpack打包,就能看到css內嵌到main.bundle.js中了,css-loader是處理css文件,style-loader是把css內嵌到瀏覽器。

less-loader 首先在src/css/里建一個less.less,內容:
@w:200px;
@h:200px;
*{
  margin: 0;
  padding: 0;
}
#box{
  div{
    width:@w;
    height:@h;
  }
}
在main.js中引入,打包,直接報錯,我們可以安裝一個less-loader來解決,安裝,npm install --save-dev less-loader less,一樣的,配置一下webpack.config.js:
{
    test: /\.less$/, use: [ { loader: "style-loader" //最后交由style-loader處理  }, { loader: "css-loader" //然后交給css-loader處理,  }, { loader: "less-loader" //當碰到less文件時,交給less-loader處理,  } ]
}

現在打包的話,less文件就被嵌入進去了。

html-loader

如果想把html內容引入的話就需要html-loader了,在src/components目錄下新建一個modal.html,內容:

<div class="modal">
    <div class="modal-heading">模態框頭部 - by ghostwu</div>
    <div class="modal-body">模態框內容部分 - by ghostwu</div>
</div>

這次就不錯誤示范了,直接安裝html-loader,npm install html-loader --save-dev,然后配置一下webpack.config.js:

{
     test: /\.(html)$/,
     use: {
       loader: 'html-loader',
     }
}

modal.js文件引入modal.html

import tpl from './modal.html';
let modal = function(){
    return {
        'component-name' : 'modal',
        'tpl' : tpl
    }
}
export default modal;

main.js對webpack_demo3目錄下的index.html文件插入模板(modal.html)

import modal from './components/modal.js';
let App = function(){
    var oApp = document.querySelector("#app");
    var oModal = new modal();
    oApp.innerHTML = oModal.tpl;
}
new App();

在index.html模板文件中建一個id為app的div,打包,

這次在dist目錄下生成的index文件中,就有了modal.html的內容。

 

file-loader

圖片資源的打包,圖片在靜態排版中,經常出現的兩個位置1,css通過background引入背景,2,還有一種就是在html模板文件中用img標簽引入的方式,如果要在webpack使用圖片資源,我們需要用file-loader來處理.如果不使用的話,就會報錯。

安裝,安裝 npm install file-loader --save-dev,配置:

{
     test: /\.(png|gif|jpg|svg|jpeg)$/i,
     use: {
         loader: 'file-loader',
         query : {
             name : 'assets/[hash].[ext]'
         }
     }
}

query部分的配置,是為打包的圖片設置一個自定義的存儲路徑和文件名稱
注意:在模板中引入圖片路徑,
如果是相對路徑要這樣引入${require(圖片的相對路徑)},否則打包路徑會出現問題

<img src="${ require('../img/dm.jpg') }" alt="">


免責聲明!

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



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