Webpack 簡介

首先,Webpack 是一個開源模塊打包工具,核心功能是解決模塊間的依賴,將模塊按照必定規則組織在一塊兒,合併爲一個或多個 .js 文件。html

瞭解過 Web 前端開發的小夥伴都知道,咱們一般都在與 HTML、CSS 和 JS 等靜態資源打交道,直接將工程中的源文件發佈到服務器不就能夠了嗎?中間過程當中加了 webpack 環節,有多大意義呢?前端

模塊化以前

一個項目在立項後,對於程序結構的設計,要是把全部代碼都堆在一個文件中,那將是很是很是很是糟糕的事情(怎麼會有人怎麼作)。更好的方式是將這些代碼按照特定功能拆分爲多個代碼段並存到多個文件中,即麼個代碼段(文件)只實現特定功能,最終纔將全部代碼段組合在一塊兒。這就是咱們熟悉的模塊化思想,相信你會不排斥這種設計思路。webpack

像 C、C++、Java 等程序語言,開發者直接可使用模塊化進行開發,但是 Javascript 在很長一段時間內只能經過 script 標籤將多個 js 文件插入到頁面中。這些都是歷史緣由了,真要追溯,那是設計 Javascript 的做者最初將 Javascript 定位成腳本語言,實現網頁動態效果,因此無需模塊化。隨着用戶對體驗的要求變高,Javascript 原來的設計思路就暴露出許多問題git

  • 手動維護 Javascript 文件加載順序,以解決文件件的依賴關係;
  • 每一個 script 標籤都須要向服務器請求一次靜態資源;
  • 全局做用域的泛濫污染;
  • ...

模塊化引入

爲了解決上述問題,就不得不引入模塊化設計思路github

  • 經過導出和導入語句來解決模塊依賴關係;
  • 模塊可藉助工具打包,合併類似功能資源文件,減小網絡開銷;
  • 模塊間的做用域是隔離的,這就解決了命令衝突;
  • ...

模塊化歷史

引入模塊化思路後,各社區前後開發了 AMD、CommonJS、CMD 等解決方案(這些或許讀者都接觸過或許都沒用過,都沒有關係,不用緊張)。2015年,ECMAScript 6.0(就是 ES6)正式定義了 Javascript 模塊標準,前先後後 20 年,這一刻終於能夠堂堂正正地說 Javascript 擁有模塊這個概念了(感動的痛哭而涕,場面一度失控,哈哈)。web

但是(我不想聽),在獲得大多數現代瀏覽器支持的同時,有些特性和功能還不能直接使用。npm

  • 沒法使用 code splitting 和 tree shaking 特性;
  • 不少 npm 模塊使用 CommonsJS 形式,而瀏覽器並不支持這類語法,因此沒法直接使用;
  • 兼容其餘瀏覽器(客戶是上帝,咱們是開發者,也要考慮用戶的體驗啊);

終於等到你

既然問題出現了,那就得有方案解決。模塊打包工具(module bundler,mb 這不是罵人那個單詞的簡稱)就是保證將打包後的文件正確無誤地運行在瀏覽器中。當下,明星產品有 webpack、parce 和 Rollup 等。json

其工做方式:瀏覽器

  • 在頁面初始化時加載入口模塊,其餘模塊按需異步加載;
  • 存在依賴關係的模塊按照必定規則合併爲單個文件,一次性加載到頁面中;

爲什麼選擇你

那爲什麼選擇 webpack 呢?(由於這本書就是講它啊,這個就不用說了)主要是 webpack 很給力,自帶特性以下,容我慢慢道來:服務器

  • 支持多種模塊標準(AMD、CommonJS、ES6模塊);
  • 支持多種類型資源的處理,好比圖片、樣式等;
  • 擁有活躍社區支持,你不是一我的在戰鬥;
  • code splitting(上面剛提過),即代碼分割,意思是分割打包後的資源,首屏只加載必要的部分,不過重要部分翻到後面動態(按需)加載。對於體積大的應用來講就是福音啊,能夠減少資源體積,提高首頁渲染速度;

安裝

依賴 Node.js 這個就不在贅述,推薦使用 Node.js 的 LTS (Long Term Support)版本。

  • 全局安裝,好處是綁定一個命令行環境變量,即一次安裝、出處運行;
  • 本地安裝,成爲項目中的依賴,只能在項目內部使用,推薦本地安裝;
    • 一般項目都不是一我的開發,因爲每一個開發者系統中的 webpack 版本不一樣,可能致使輸出結果也不一樣(相信這不是你我所但願看到的);
    • 部門插件(依賴 webpack)會調用項目中 webpack 的內部模塊,此時就得本地安裝,若此時你全局安裝本地未安裝,容易致使問題不明確,耽誤時間;

代碼編寫

1.建立 myapp/01,而後執行安裝命令

npm init -y

npm i webpack webpack-cli -D
複製代碼

2.編寫 01/index.html01/index.js01/util.js 文件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>01 webpack</title>
  </head>
  <body>
    <script src="./dist/bundler.js"></script>
  </body>
</html>
複製代碼
// 01/index.js
import util from './util';

document.write('我是主文件');
setTimeout(util, 3000);
複製代碼
// 01/util.js
export default function() {
  document.write('我是依賴文件');
}
複製代碼

3.打包執行

命令行直接輸入執行

npx webpack --entry=./index.js --output-filename=bundler.js --mode=development
複製代碼

或修改 package.json 中的 scripts,而後命令行執行 npm run build

// 01/package.json
"scripts": {
  "build": "webpack --entry=./index.js --output-filename=bundler.js --mode=development",
},
複製代碼
  • entry,入口文件,查找模塊依賴找到 util.js,而後一塊兒打包成一個文件;
  • output-filename,輸出資源名;
  • mode,打包模式,其中參數有 development、production、none 三種;

4.在瀏覽器打開 index.html 文件;

完整代碼可查看目錄 01 =>O(∩_∩)O~

藉助配置文件

其實像上面打包方式,參數寫在命令中,雖可行但囉嗦不耐看,一旦打包需求複雜,那將是災難,因此咱們得藉助配置文件,簡化打包命令。可查看 myapp/02

// 02/webpack.config.js
const webpackConfig = {
  entry: './src/index.js',
  output: {
    filename: 'bundler.js'
  },
  mode: 'development'
};

module.exports = webpackConfig;
複製代碼

此時,對應 package.json 中的 scripts 可簡化爲

// 02/package.json
"scripts": {
  "build": "webpack"
}
複製代碼

完整代碼可查看目錄 02 =>O(∩_∩)O~

符合人類的開發環境

不知道你可發現,每次改變文件,都要打包,而後才能刷新看到結果(天啊,世上還有更爛的開發環境麼?)。因此,咱們得改變,webpack-dev-seaver 就要登場了,從文件名就可看出其功能提供 webpack 開發服務。既然是開發,那就說明在發生產時不須要此包,那安裝就是 npm install webpack-dev-seraver -D

其主要功能是服務啓動時,讓 webpack 模板打包並生成靜態資源,待接收瀏覽器請求後,進行 url 校驗,若是地址正確(即配置參數 publicPath),就從打包結果(內存)中找到對應資源(此刻請求的文件 bundler.js 只在內存中,未寫入到實際硬盤 bundler.js 中,驗證這點很簡單,刪除 03/release 目錄,你會發現即時沒有該目錄依舊能夠訪問文件 /release/bundler.js )返回給瀏覽器,若是不正確,就從硬盤讀取資源文件返回給瀏覽器。寫入內存,讀取速度很快,若是每次都刪除磁盤文件而後再寫入,性能明顯低下。

// 03/webpack.config.js
const webpackConfig = {
  entry: './src/index.js',
  output: {
    filename: 'bundler.js'
  },
  mode: 'development',
  devServer: {
    publicPath: '/release',
    port: '1989',
    open: true
  }
};

module.exports = webpackConfig;
複製代碼
  • 配置文件新增了 devServer 對象,主要配置 webpack-dev-server;
  • publicPath 是開發環境靜態資源的地址(內存中),這裏爲了能體現出效果,本該設置 /dist,現改成 /release
  • port 就是端口了;
  • open 設爲 true,即當服務啓動好後,自動打開地址 http://localhost:1989(太人性化了,my love);
  • ...(其餘參數之後篇幅會涉及,不要着急,年輕人)

既然靜態資源地址改了,那咱們 HTML (03/src/index.html) 也得配合修改

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>03 webpack</title>
  </head>
  <body>
    <script src="./release/bundler.js"></script>
  </body>
</html>
複製代碼

此刻,你能夠改下 03/index.js03/util.js 文件,瀏覽器會自動刷新是否是(我知道你看到了),這是 webpack-dev-server 的自動刷新(live-reloading)功能。再一次提高了本地開發的效率。

經過親自實踐,咱們能夠總結:webpack-dev-server 至少有如下幾點功能:

  • 提供處理靜態資源文件請求的本地服務(服務器都該能幹的事);
  • 提供 webpack 模塊打包;
  • live-reloading,自動刷新瀏覽器功能,即監聽文件變化;

完整代碼可查看目錄 03 =>O(∩_∩)O~

上一篇:webpack 前言

相關文章
相關標籤/搜索