webpack (1)——核心概念的理解

引子

爲何要寫這篇文章?由於今天掘金的早報有一篇關於 Webpack 的入門的文章,讀完以後發現本身確實該學習一下 Webpack 了,因此有了這篇文章。
我對於 webpack 的瞭解僅限於在 vue-cli 中接觸過,固然都是現成的,本身也從沒操做過。
可是隨着本身的成長,這些必需要了解一下,接下來簡單都構建一個屬於本身的 webpack 打包工具...css

  1. webpack (1)——核心概念的理解
  2. webpack(2)——配置項詳解
  3. ...

初試 webpack

我在初次學習新東西的時候,都會先先弄懂三個問題:html

  1. 它是什麼東西;
  2. 它能幹什麼;
  3. 它每一步大致是什麼意思。

概念

webpack 文檔中是這樣定義的:vue

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

image

配合其官網的首頁圖不難理解其含義:一切文件如:JavaScriptCSSSASSIMG/PNG等,在 Webpack 眼中都是一個個模塊,經過對 Webpack 進行配置,對模塊進行組合和打包。通過 Webpack 的處理,最終會輸出瀏覽器能使用的靜態資源。react

核心概念

基本理解了什麼是 Webpack 、能幹什麼以後,接下來就開始理一下如何使用它。 順着 Webpack 的文檔學習,在正式使用以前,它須要咱們理解幾個核心概念:webpack

  • Entry 入口
  • Output 輸出結果
  • Loader 模塊轉換器
  • Module 模塊
  • Chunk 代碼塊
  • Plugin 插件

Entry

entry 是配置模塊的入口,它指示 Webpack 執行構建的第一步。
能夠在配置文件中配置 entry 屬性,來指定一個或多個入口點git

entry 類型有三種:字符串、數組、對象。es6

  • String"./src/entry" 入口模塊的文件路徑,能夠是相對路徑
  • array : ["./src/entry1", "./src/entry2"] 入口模塊的文件路徑,能夠是相對路徑。與字符串類型不一樣的是數組可將多個文件打包爲一個文件
  • object{ a: './src/entry-a', b: ['./src/entry-b1', './app/entry-b2']} 配置多個入口,每一個入口有一個 Chunk

Output

output 配置如何輸出最終想要的代碼。output 是一個 object,裏面包含一系列配置項。github

  • filename 用於輸出文件的文件名。
  • path 目標輸出目錄的絕對路徑,必須是絕對路徑。

module、Loader

module 配置如何處理模塊web

配置Loader

Loader 能夠看做具備文件轉換功能的翻譯員,配置裏的 module.rules 數組配置了一組規則,告訴 Webpack 在遇到哪些文件時使用哪些 Loader 去加載和轉換。

  • use 屬性的值須要是一個由 Loader 名稱組成的數組,Loader 的執行順序是由後到前的;
  • 每個 Loader 均可以經過 URL querystring 的方式傳入參數,例如 css-loader?minimize 中的 minimize 告訴 css-loader 要開啓 CSS 壓縮。

Plugins

Plugin 用於擴展 Webpack 功能,各類各樣的 Plugin 幾乎讓 Webpack 能夠作任何構建相關的事情。

配置 Plugin

Plugin 的配置很簡單,plugins 配置項接受一個數組,數組裏每一項都是一個要使用的 Plugin 的實例,Plugin 須要的參數經過構造函數傳入。

固然使用 Plugin 的難點在於掌握 Plugin 自己提供的配置項,而不是如何在 Webpack 中接入 Plugin

想實現某項 Webpack 沒有的功能去 gayHub 碰碰運氣吧!哦不,是 github 碰碰運氣吧!

Chunk

Chunk,代碼塊,即打包後輸出的文件。

Webpack 會爲每一個 Chunk 取一個名稱,能夠根據 Chunk 的名稱來區分輸出的文件名。

filename: '[name].js'
複製代碼

一個入口文件,默認 chunknamemain。 除了內置變量 name,與 chunk 相關的變量還有:

  • id Chunk 的惟一標識,從0開始
  • name Chunk 的名稱
  • hash Chunk 的惟一標識的 Hash
  • chunkhash Chunk 內容的 Hash

簡單配置一個 webpack

瞭解了基本概念就直接開車吧,咳咳咳,開始實戰。

// ./webpack.config.js

module.exports = {
    mode: 'development',
    entry:{
        app1: './src/index.js',
        app2: './src/main.js'
    },
    output: {
        path: __dirname + '/dist',
        filename: '[hash][name].js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                loader: 'style-loader!css-loader'
            },
            {
                test: /\.js$/,
                use: 'babel-loader',
                exclude: /node_modules/
            }
        ]
    }
};
// ./src/index.css
html {
    background: #333;
    color: #fff;
}
// ./src/index.js
import './index.css'
const sleep = async time => await new Promise( resolve => {
    setTimeout( () => {
       console.log(`等待${time}s`)
        return resolve
    }, time*1000)
} )
sleep(5)
console.log(`Success!`)

// ./src/main.js
const sleep = async time => await new Promise( resolve => {
    setTimeout( () => {
        console.log(`等待${time}s`)
        return resolve
    }, time*1000)
} )
sleep(2)


// .babelrc
{
  "presets": [
    "es2015",
    "stage-0"
  ],
  "plugins": [
    ["transform-runtime", {
      "polyfill": false,
      "regenerator": true
    }]
  ]
}

// package.json
{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "dependencies": {
    "babel-core": "^6.26.3",
    "babel-polyfill": "^6.26.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "css-loader": "^0.28.11",
    "style-loader": "^0.21.0",
    "webpack": "^4.8.3",
    "webpack-cli": "^2.1.3"
  },
  "devDependencies": {
    "babel-loader": "^7.1.4",
    "babel-plugin-transform-runtime": "^6.23.0"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Aditya",
  "license": "ISC"
}

複製代碼

上述代碼是我寫的第一個 webpack demo,入門是真的簡單,因此很快的根據文檔配置了一個可以打包 css、es六、async/awaitWebpack

其中一些依賴項的安裝以下

// npm i -D 是 npm install --save-dev 的簡寫
npm i -D webpack webapck-cli

npm i -D css-loader style-loader

npm i -D babel-loader babel-core babel-polyfill babel-preset-es2015 babel-preset-stage-0 babel-plugin-transform-runtime
複製代碼

css-loader和style-loader

在配置過程當中遇到的問題:css代碼被打包了,卻沒有生效。

一開始在配置 Loader 中,我只寫了 css-loader,由於今天看的博文中的栗子就只寫 css-loader , 卻不知人家根本就沒寫任何 CSS 樣式=。=

因此善用了一下手中的搜索引擎,從而得知這個過程應該是這樣的:

Webpack 在遇到以 .css 結尾的文件時先使用 css-loader 讀取 CSS 文件,再交給 style-loaderCSS 內容注入到 JavaScript 裏。

style-loader 的工做原理大概是這樣的:把 CSS 內容用 JavaScript 裏的字符串存儲起來, 在網頁執行 JavaScript 時經過 DOM 操做動態地往 head 標籤裏插入 style 標籤。

再來講說 babel

瞭解 ES 6 的同窗都應該知道,目前部分瀏覽器和 Node.js 已經支持 ES6,但因爲它們對 ES6 全部的標準支持不全,這致使在開發中不敢全面地使用 ES6。 一般咱們須要把採用 ES6 編寫的代碼轉換成目前已經支持良好的 ES5 代碼,這包含兩件事:

  1. 把新的 ES6 語法用 ES5 實現,例如 ES6 的 class 語法用 ES5 的 prototype 實現。
  2. 給新的 API 注入 polyfill ,例如使用新的 fetch API 時注入對應的 polyfill 後才能讓低端瀏覽器正常運行。

Babel 能夠方便的完成以上2件事。 Babel 是一個 JavaScript 編譯器,能將 ES6 代碼轉爲 ES5 代碼,讓你使用最新的語言特性而不用擔憂兼容性問題,而且能夠經過插件機制根據需求靈活的擴展。

Babel 執行編譯的過程當中,會從項目根目錄下的 .babelrc 文件讀取配置。.babelrc 是一個 JSON 格式的文件,內容大體以下:

{
  "presets": [
    "es2015",
    "stage-0"
  ],
  "plugins": [
    ["transform-runtime", {
      "polyfill": false,
      "regenerator": true
    }]
  ]
}
複製代碼

babel-loader

babel-loader 是必須的,在 Webpack 經過 Loader 接入 Babel,完成轉碼

babel-preset-es2015和babel-preset-stage-0

presets 屬性告訴 Babel 要轉換的源碼使用了哪些新的語法特性,一個 Presets 對一組新語法特性提供支持,多個 Presets 能夠疊加。 Presets 實際上是一組 Plugins 的集合,每個 Plugin 完成一個新語法的轉換工做。

  1. 已經被寫入 ECMAScript 標準裏的特性,因爲以前每一年都有新特性被加入到標準裏,因此又可細分爲:
  • es2015 包含在2015里加入的新特性;
  • es2016 包含在2016里加入的新特性;
  • es2017 包含在2017里加入的新特性;
  • es2017 包含在2017里加入的新特性;
  • env 包含當前全部 ECMAScript 標準裏的最新特性。
  1. 被社區提出來的但還未被寫入 ECMAScript 標準裏特性,這其中又分爲如下四種:
  • stage0 只是一個美好激進的想法,有 Babel 插件實現了對這些特性的支持,可是不肯定是否會被定爲標準;
  • stage1 值得被歸入標準的特性;
  • stage2 該特性規範已經被起草,將會被歸入標準裏;
  • stage3 該特性規範已經定稿,各大瀏覽器廠商和 Node.js 社區開始着手實現;
  • stage4 在接下來的一年將會加入到標準裏去。

3.爲了支持一些特定應用場景下的語法,和 ECMAScript 標準沒有關係,例如 babel-preset-react 是爲了支持 React 開發中的 JSX 語法。

babel-plugin-transform-runtime

Plugin 屬性告訴 Bable 要使用那些插件,插件能夠控制如何轉換代碼。

官方給出的定義是: babel-plugin-transform-runtimeBabel 官方提供的一個插件,做用是減小冗餘代碼。 可是咱們爲何要使用它?主要是由於使用 ES 7async 函數。

由於 runtime 編譯器插件作了如下三件事:

  • 當你使用 generators/async 函數時,自動引入 babel-runtime/regenerator
  • 自動引入 babel-runtime/core-js 並映射 ES 6 靜態方法和內置插件。
  • 移除內聯的 Babel helper 並使用模塊 babel-runtime/helpers 代替。

該插件的具體信息:transform-runtime

至於 babel 的其餘的具體用法,能夠查閱 Babel官方文檔

寫在最後

對於 Webpack 第一步學習就到這裏結束了,翻閱的資料有點多,須要學習的東西太多了,一時半會也記不住,算是鋪個路吧,但願從此的學習可以順暢一些。 歡迎大佬指點不足之處。

相關文章
相關標籤/搜索