webpack基礎入門

来源:http://www.cnblogs.com/Uncle-Keith/archive/2017/02/03/6363304.html
-Advertisement-
Play Games

我相信,有不少的朋友對webpack都有或多或少的瞭解。網上也有了各種各樣的文章,文章內作者也寫出了不少自己對於webpack這個工具的理解。在我剛剛接觸webpack的時候,老實說,網上大部分的文章我是看不懂的。。webpack裡面有很多名詞,是沒有接觸和理解過模塊化的同學都難以理解的。我感覺,學 ...


我相信,有不少的朋友對webpack都有或多或少的瞭解。網上也有了各種各樣的文章,文章內作者也寫出了不少自己對於webpack這個工具的理解。在我剛剛接觸webpack的時候,老實說,網上大部分的文章我是看不懂的。。webpack裡面有很多名詞,是沒有接觸和理解過模塊化的同學都難以理解的。我感覺,學習任何一項新技術,要弄清楚為什麼使用它,它是什麼,它有什麼用等概念,弄清楚這些概念之後,我相信,在日後的webpack學習中會達到事半功倍的效果。這篇文章,我會以最簡單的方式,闡述什麼是webpack。當然,這是我個人對webpack的一些理解,也是在學習中總結。

另外,最好的學習webpack的資源是webpack的官網。傳送門:webpack

當然,如果你早已是webpack的實踐者,對webpack認識足夠深入,這篇文章不太適合您閱讀。如果你是小白,那就可以開啟webpack的探索之路了。

webpack是目前流行的一款模塊化打包工具。

webpack定義:一款前端資源模塊化和打包工具。

webpack作用:

1. 將許多鬆散的模塊按照依賴關係和規則打包成符合生產環境環境部署的前端資源。
2. 將按需載入的模塊進行代碼分割,等到實際需要的時候再非同步載入。
3. 通過載入器loader的轉換,所有的前端資源都可以看作是模塊。比如說CommonJS模塊,AMD模塊,ES6模塊,css,sass,json,圖片等。

短短的幾句話,就有太多讓人難以明白的地方。

1. 什麼是前端資源?

2. 什麼是模塊?

3. 什麼是模塊化?

4. 什麼叫按需載入?

5. 如何實現按需載入?

6. 什麼是plugins?

7. 什麼是loader?

什麼是前端資源

所謂前端資源,就是我們在創建html時,引入的script,link,img,json等文件。webpack足夠的優秀,只需要在html文件中引入一個js文件,在定義一個入口文件js,用於存放依賴的模塊,就可以將其他前端資源按照依賴關係和規則打包。

以前我們需要這樣來引入文件。

<link rel="stylesheet" href="style/stylesheets/screen.css"  media='screen'/ >
<script src='script/jquery-2.2.1.min.js'></script>
<script src='script/bootstrap.js'></script>
<script src="script/index.js" ></script>

index.js依賴bootstrap.js,而bootstrap又依賴於jquery。我們必須按照DOM順序來寫每一個js文件。

現在只需要在html中引入一個主文件index.js,其他依賴的前端資源都寫在另外一個入口文件js中,這個入口文件不用寫在html中,然後配置好config,在cmd中輸入webpack執行編譯,所有前端資源都被引入了。並且webpack會幫我們入口文件entry.js的每個模塊的類型和依賴關係,等到需要的時候再按需載入。

//html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src='js/main.js'></script>
<!-- 引入引入主模塊 main.js -->
</body>
</html>

//entry.js
import $ from 'jquery';
import other...

什麼是模塊

在webpack中,所有的前端資源都是模塊,可以通過載入器loader進行轉換。在javascript方面,有幾大模塊系統,CommonJS模塊,AMD模塊,CMD模塊,ES6模塊。談談我對這幾大模塊的理解。

CommonJS

在CommonJS中,有一個全局方法require(),用於載入依賴模塊。

//main.js
var jquery = require('jquery');
var bootstrap = require('bootstrap');

主文件main.js模塊依賴於這兩個模塊,CommonJS缺點就是同步載入。也就是說,會先載入jquery模塊,等到jquery載入完了再去載入bootstrap模塊。引用阮一峰老師的話

同步載入意味著阻塞載入,當依賴的模塊太大時,瀏覽器會處於假死的狀態。

假死意味著瀏覽器任然處在載入中,仍然還是空白頁面。這種假死的狀態帶來的後果就是用戶的離開。

AMD模塊

AMD也叫非同步模塊定義,英文Asynchronous Module Definition。AMD是requirejs對模塊定義時的產出。它採用非同步方式載入模塊,每個獨立模塊的載入不影響回調函數中定義的模塊的運行。在回調函數中定義一個模塊,只有當依賴的模塊載入完成之後,該模塊才會編譯執行。AMD也採用require()語句來載入一個模塊,但是不同於CommonJS,它有兩個參數。第一個參數是數組,需要傳入依賴模塊;第二個參數是回調函數,回調函數中也接受參數,而參數是形式參數,來自於每一個依賴模塊。舉個例子。

//main.js
require(['jquery','bootstrap'],function($, boot){
    //寫入的模塊
})

主模塊main.js依賴於jquery,Bootstrap模塊,main只有在這兩個模塊載入完成之後才會編譯執行main定義的模塊,屬於同步載入。而在兩個依賴模塊中,屬於非同步載入。也就是說bootstrap不用等到jquery載入完成之後再載入,被依賴的模塊是哪一個模塊小,就先載入哪一個,這就避免了CommonJS模塊中同步載入依賴模塊而出現瀏覽器假死的狀態。稍微總結一下,
主模塊需要等到依賴模塊載入完成之後才編譯執行,屬於同步載入;而被依賴模塊之間屬於非同步載入,哪一個模塊小,就先載入哪一個。

AMD模塊的一大不足就是所有依賴的模塊都需要提前載入,依賴前置。

CMD模塊

CMD模塊跟AMD很相似,這裡引用玉伯老師的話看看CMD和AMD的區別。

對於依賴的模塊,AMD是提前執行,CMD是延遲執行。

CMD推從依賴就近,AMD推從依賴前置

依賴就近的意思就是當我需要某個模塊的時候再去非同步載入。也就是按需要載入前端資源,懶載入。
可以用八個字來總結CMD。依賴就近,延遲執行。

ES6模塊

ES6模塊的設計思想,是儘量的靜態化,使得編譯時就能確定模塊的依賴關係,以及輸入和輸出的變數。ES6中與CommonJS,AMD模塊一個區別在於ES6是通過import關鍵字來輸入某個模塊提供的功能,export或者export default規定該模塊的對外介面,通俗易懂一些,也就是暴露該模塊定義的一些屬性和方法,供其他模塊調用。

ES6和CommonJS,AMD模塊最大的區別在於,ES6模塊可以實現編譯時載入,簡單的說就是按需載入。而後兩種方法只能是運行時載入。上一段代碼。

ES6:
import {get, post, ajax} from 'jQuery';

CommonJS:
var 

什麼是模塊化

webpack是支持以上的模塊系統的。在頭腦中要形成某種技術的知識框架才能學好該技術,所以花費了一些時間做了些介紹。模塊化就是webpack使用某種方法將每一個鬆散的模塊按照依賴關係編譯的過程。webpack需要一個入口js文件,主模塊js文件,config文件就可以實現前端資源模塊化。看個簡單的例子。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src='js/main.js'></script>
1. <!-- 引入主模塊 main.js -->
</body>
</html>

2. //入口文件 entry.js 
document.write("<h1>I'm Uncke Keith!</h1>");

3. //webpack.config.js
module.exports = {
    entry :'./app/js/entry.js',
    output : {
        path: './dist/js'
        filename: 'main.js'
    }
};

4. //打開cmd,在文件目錄下,輸入webpack執行編譯就可以看到document.write()的結果了。

什麼叫按需載入?

webpack的其中一個作用就是可以將按需載入的模塊進行代碼分割,根據實際需要進行非同步載入。按需載入,顧名思義就是按照用戶需要某個功能的時候在載入相應的模塊。舉個例子,當我們在瀏覽一些圖片網站的時候,如果圖片在你打開該網站的時候就全部一起載入好,那造成的後果就是頁面會保持一段時間的空白狀態,直到全部圖片載入完成之後才會顯示。如果是按需要載入,就可以在用戶剛進入頁面的時候載入可視區域視窗的圖片,當用戶拖動滾動條下拉的時候再去載入圖片,這樣不僅減少HTTP請求,同時提高了頁面載入速度。在舉一個例子。在單頁應用中,為了減少http請求次數,會把所有js文件合併為一個文件,這樣請求數量減少了,可是請求的文件體積卻變大了。按需載入就可以解決這個問題。

如何實現按需載入?

ES6的一大涉及思想就是想讓前端資源靜態化,在編譯的過程中,而非運行過程中就確定模塊的依賴關係。webpack在編譯的過程中,就會對整個代碼進行靜態分析,分析出各個模塊的類型和它們依賴關係,然後將不同類型的模塊提交給適配的載入器來處理。比如一個用 Sass 寫的樣式模塊,可以先用 Sass-Loader載入器將它轉成一個CSS 模塊,在通過 CSS 模塊把他插入到頁面的 style 標簽中執行。並且在你編譯的時候就確定了依賴關係。

什麼是plugins?

webpack跟我們提供了很多內置的插件,可以實現loader做不到的事情。在這裡介紹幾個常用的插件。

1. extract-text-webpack-plugin

我們在入口文件中import(或者require)進一些css文件時,webpack會幫我們把css樣式與其他前端資源打包到output的filename文件中,然後在head標簽中會自動載入一個style標簽。但是,我們可能會需要獨立出一個css文件,這時候就需要使用extract-text-webpack-plugin插件了。具體用法如下:

var ExtractTextPlugin = require("extract-text-webpack-plugin");
//這裡需要使用CommonJS語法來引入一個依賴。

module.exports = {
    module: {
        loaders: [
            { test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader") }
            //loader的執行順序是 先執行css-loader給css文件加上地址,然後執行style-loader在頭部加上style標簽。
        ]
    },
    plugins: [
        new ExtractTextPlugin("styles.css")
        //使用plugins選項對象,使用new調用ExtractTextPlugin構造函數,傳入的參數是需要單獨生成的css文件,路徑與output中的path路徑相同。詳細的參數可以到extract-text-webpack-plugin官網查看。
    ]
}

當我們成功生成了單獨的css文件之後,就可以通過link標簽引入了。

什麼是loader?

Webpack 本身只能處理原生的 JavaScript 模塊,但是 loader 轉換器可以將各種類型的資源轉換成 JavaScript 模塊。這樣,任何資源都可以成為 Webpack 可以處理的模塊。每一個loader都會針對入口文件entry.js的依賴模塊引入的前端資源進行轉換。站在更高的角度上看問題,我們在webpack.config.js裡面的所有配置都是針對入口文件的,始終記住這點很重要。因為這就是我們配置webpack.config.js的目的。在這裡介紹一些常用loader。

1. postcss-loader

我是一名sass實踐者,並且用著一個封裝了很多mixins的compass庫,這個庫的最大好處就是可以直接include一些compass封裝好的的css3的mixin時,編譯之後會幫我們加上css首碼。如果想在.vue中也實現這種自動首碼的功能,可以使用webpack給我們提供的postcss-loader。(可以去官網查看相關介紹)。postcss?這又是什麼鬼,其實postcss只是一個平臺,我們需要用的是基於postcss平臺上的一些常用的插件。

如果想使用這個插件,需要下載一些依賴。

cnpm install autoprefixer --save-dev
//autoprefixer用於添加css3首碼

具體的webpack.config.js配置如下

//註意先引入依賴
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var autoprefixer = require('autoprefixer'); 

module.exports = {
    entry: __dirname + '/app/entry.js',
    output: {
        path: __dirname + '/dist',
        filename: 'bundle.js'
    },
    module: {
        config...
    },
    postcss:[
        autoprefixer()
    ]
};

如果你的入口文件entry.js是這樣的。

...
import './assets/main.scss';

那麼當然你在main.scss使用scss語法寫一些css3屬性時,在編譯之後就可以看到css3首碼了。但是如果你的樣式是寫在*.vue組件裡面的

比如說,入口文件entry.js是這樣的。

...
import app from './app.vue';

topBar.vue

<template>
    config...
</template>

<script>
    config...
</script>
<style lang='sass' scoped>
    .main{
        font-weight: bold;
        p {
            border-radius: 10px;
            box-shadow: 3px 3px 3px #ccc;
            transition: all 0.3s;   此處測試css3的屬性首碼
        }
    }
</style>

在瀏覽器中查看效果,你會發現,.vue組件中定義的style樣式並沒有加上屬性首碼。

.main p[data-v-a64cfc10] {
    background-color: red;
    border-radius: 10px;
    box-shadow: 3px 3px 3px #ccc;
    color: red;
    display: inline-block;
    font-weight: bold;
    height: 100px;
    transition: all 0.3s ease 0s;
}

難道是postcss-loader失效了?其實並不是。出現這種情況的原因主要還是對vue-loader不熟悉導致的。因為你是把樣式寫在了單個*.vue組件中,所以這裡會涉及另外一個lodaer,也就是Vue官方提供的vue-loader。在vue-loader中如果也想讓樣式擁有首碼,在webpack.config.js要進行如下配置。

module.exports = {
    entry: ... ,
    output: { ... },
    module: { ... },
    這裡配置vue指的是vue-loader,我們需要在vue-loader中再一次配置postcss。
    vue: {
        postcss: [require('autoprefixer')()],
        autoprefixer: true
    },
    postcss:[
        autoprefixer()
    ]
    //也就是說,postcss需要配置兩處。一是解析entry.js中引入的css模塊;一處是解析
    單個*.vue組件的<style>標簽中的樣式。
}

執行編譯,你會發現正常顯示了。

持續更新中..



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • animation-play-state介紹 animation-play-state 屬性規定動畫正在運行還是暫停。 瀏覽器支持:Internet Explorer 10、Firefox 以及 Opera 支持 animation-play-state 屬性。Safari 和 Chrome 支持替 ...
  • 3D地圖又叫場景。 由上一篇可知, require入口函數的第一個參數是字元串數組 ["esri/Map", "esri/views/MapView", "dojo/domReady!"] 這裡,MapView就是2D的地圖視圖。 所以,將2D地圖改為3D地圖,其實很簡單,只需要把這個字元串數組的第 ...
  • jQuery 選擇器簡介 jQuery 選擇器允許對 HTML 元素組或單個元素進行操作。 jQuery 選擇器基於元素的 id、類、類型、屬性、屬性值等"查找"(或選擇)HTML 元素。 它基於已經存在的 CSS 選擇器,除此之外,它還有一些自定義的選擇器。 jQuery 中所有選擇器都以美元符號 ...
  • 效果如下: 祝我明天面試順利,一切順利! ...
  • 例如:求字元串'nininihaoa'中出現次數最多字元 結果如圖所示: ...
  • 關於正則表達式匹配中獲取所有匹配點時,匹配點的開始位置遇到的問題 輸出結果如下: 輸出結果如下: 第二段代碼輸出結果的原因是正則表達式只使用了一次,正則對象中記錄的是此次匹配所找到的匹配點,導致三次輸出結果相同 對於正則對象中每次進行匹配的匹配點進行瞭如下測試: 1.改變字元串長度 輸出結果如下: ...
  • 介紹幾個js DOM的常用方法 獲取元素節點 getElementById getElementsByTagName getElementsByClassName 先寫一個簡單的網頁做測試: 1. getElementById 1.先定義變數 var contentId = document.get ...
  • RegExp對象是原生JavaScript中表示正則表達式的對象。 創建對象的方法為:var RegExp = new RegExp(pattern, attributes); 參數pattern指定正則表達式的規則或者表示正則表達式模式的字元串;參數attributes為可選參數,表示匹配模式的修 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...