[譯]Webpack 2和模板打包的初學者指南(上)

Webpack是模塊打包工具。css

Webpack已成爲現代Web開發最重要的工具之一。首先,它是一個JavaScript模板打包工具,他能轉換全部的前端資源,如HTML和CSS,甚至圖片。它可讓你更好地控制你應用程序的HTTP請求數量,並容許你使用其餘的風格資源(如Jade,Sass和ES6)。Webpack還容許你輕鬆地從npm上使用軟件包。html

本文面向剛剛接觸Webpack的初學者,主要介紹Webpack的初始設置和配置、模板、加載程序、插件、代碼拆分和熱模塊替換。若是你發現視頻教程對你更有幫助,我強烈推薦Glen Maddern’s的Webpack from First Principles做爲一個起點,瞭解是什麼使得Webpack那麼特別。前端

接下來,你須要有Node.js installed環境,你也能夠 download the demo app from our Github reponode

Setup

讓咱們用npm新建一個項目並初始化,安裝Webpack:webpack

mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack@beta --save-dev
mkdir src
touch index.html src/app.js webpack.config.js

編輯這些文件:git

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello webpack</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="dist/bundle.js"></script>
  </body>
</html>
// src/app.js
const root = document.querySelector('#root')
root.innerHTML = `<p>Hello webpack.</p>`
// webpack.config.js
const webpack = require('webpack')
const path = require('path')

const config = {
  context: path.resolve(__dirname, 'src'),
  entry: './app.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [{
      test: /\.js$/,
      include: path.resolve(__dirname, 'src'),
      use: [{
        loader: 'babel-loader',
        options: {
          presets: [
            ['es2015', { modules: false }]
          ]
        }
      }]
    }]
  }
}

module.exports = config

上面的配置是一個常見的起點,它指示webpack將咱們的入口點src/app.js編譯輸出到/dist/bundle.js中,全部的.js文件將經過BabelES2015轉換到ES5github

爲了讓它運行,咱們須要安裝三個包:babel-coreWebpack模塊和資源轉換器——babel-loader和預設的babel-preset-es2015
{ modules: false }啓用Tree Shaking把咱們包中不被使用的輸出刪除,從而下降文件大小。web

npm install babel-core babel-loader babel-preset-es2015 --save-dev

最後,將package.json文件中的script部分替換爲:npm

"scripts": {
  "start": "webpack --watch",
  "build": "webpack -p"
},

在命令行中運行npm start來監視模式啓動webpack——每當咱們src目錄中的.js文件更改時,都會從新編譯輸出到bundle中。控制檯中的輸出會告訴咱們正在建立的包,重要的是要注意包的數量和大小。
圖片描述
如今你應該能夠在瀏覽器中加載index.html,並使用「Hello webpack」。json

open index.html

打開dist/bundle.js查看webpack作了什麼,頂部是webpack的模板引導代碼,底部是咱們的模板。也許你對這不會有很深入的印象,但若是你跟着進度學到了這裏,你能夠運用ES6 modulewebpack生產一個能在全部瀏覽器中運行的用於生產的包。

輸入命令行Ctrl + C中止webpack,並運行npm run build用於在生產模式下編譯咱們的包。

請注意,此時包的大小已經從2.16kB降低到585字節。
再查看一下dist/bundle.js,你會看到一個醜惡的代碼,咱們的包已經壓縮或醜化(uglify/minify),代碼運行效果是同樣的,但它並不符合最少字符須要。

Modules

開箱即用的webpack知道如何使用各類格式的JavaScript模塊,最顯著的兩種是:

  • ES2015的import語句

  • CommonJS的require()語句

咱們能夠經過安裝lodash並從app.js導入它來測試一下:

npm install lodash --save
// src/app.js
import {groupBy} from 'lodash/collection'

const people = [{
  manager: 'Jen',
  name: 'Bob'
}, {
  manager: 'Jen',
  name: 'Sue'
}, {
  manager: 'Bob',
  name: 'Shirley'
}, {
  manager: 'Bob',
  name: 'Terrence'
}]
const managerGroups = groupBy(people, 'manager')

const root = document.querySelector('#root')
root.innerHTML = `<pre>${JSON.stringify(managerGroups, null, 2)}</pre>`

運行npm start啓動webpack,刷新一下index.html頁面,你能夠看到按manager排序的人數組。

讓咱們來把people數組移動到本身的people.js文件中:

// src/people.js
const people = [{
  manager: 'Jen',
  name: 'Bob'
}, {
  manager: 'Jen',
  name: 'Sue'
}, {
  manager: 'Bob',
  name: 'Shirley'
}, {
  manager: 'Bob',
  name: 'Terrence'
}]

export default people

咱們可使用相對路徑簡單地從app.js導入它。

// src/app.js
import {groupBy} from 'lodash/collection'
import people from './people'

const managerGroups = groupBy(people, 'manager')

const root = document.querySelector('#root')
root.innerHTML = `<pre>${JSON.stringify(managerGroups, null, 2)}</pre>`

注意:沒有相對路徑的導入,如lodash/collection是從npm安裝到node_modules的模塊,本身寫的模塊是須要加一個相對路徑,如./people來告訴webpack區分好各個模塊。

Loaders

咱們已經介紹了babel-loader——不少loders之一,經過配置用於告訴webpack當遇到不一樣文件類型的import時要怎麼作。你能夠把過個loader整合在一塊兒,咱們能夠經過從JavaScript中導入Sass來很好地瞭解這是如何工做的。

Sass

這種轉換涉及到三個獨立的loadernode-sass庫:

npm install css-loader style-loader sass-loader node-sass --save-dev

webpack.config.js中給咱們的.scss文件添加新的配置規則:

// webpack.config.js
rules: [{
  test: /\.scss$/,
  use: [
    'style-loader',
    'css-loader',
    'sass-loader'
  ]
}, {
  // ...
}]

注意:每次更改webpack.config.js中的任何規則時,都須要使用Ctrl+Cnpm start命令從新啓動項目。

loader數組會以相反的順序執行:

  • sass-loader 把Sass轉換成CSS

  • css-loader 把CSS解析到JavaScript中,並分解全部的依賴關係

  • style-loader 把咱們的CSS輸出到文檔中的<style>標籤中

你能夠把它當作函數調用,一個loader的輸出會做爲input輸入下一個。

styleLoader(cssLoader(sassLoader('source')))

讓咱們來添加一個Sass源文件:

/* src/style.scss */
$bluegrey: #2B3A42;

pre {
  padding: 20px;
  background: $bluegrey;
  color: #dedede;
  text-shadow: 0 1px 1px rgba(#000, .5);
}

你如今能夠從JavaScript中直接請求Sass,從app.js的頭部引入:

// src/app.js
import './style.scss'

// ...

刷新一下index.html你就會看到剛添加的樣式了。

CSS in JS

咱們剛剛從JavaScript中導入了Sass文件,做爲一個模塊。

打開dist/bundle.js文件並搜索「pre {。事實上,咱們的Sass已經被編譯成一個CSS字符串,並保存爲咱們的bundle中的一個模板。當咱們在JavaScript中導入此模板時,style-loader會將該字符串輸出到嵌入的<style>標籤中。

我知道你確定是在想,爲何會這樣?

我不會在這裏深刻討論這個話題,可是你能夠從如下幾個方面考慮:

  • 你可能但願包含在項目中的JavaScript組件依賴於其餘資源(HTML、CSS、Images、SVG)來正常運行,若是這些資源能夠整合在一塊兒,那麼導入和使用就會容易不少。

  • 消除死代碼:當JS代碼不須要導入JS組件時,將再也不導入CSS,生成的bundle只會包含執行某些操做的代碼。

  • CSS模塊:CSS的全局命名空間使得開發者很難確信CSS的一個更改不會產生任何的反作用。CSS modules經過在默認狀況下使CSS local和暴露在JavaScript下使用的惟一類名來改變這一問題。

  • 經過巧妙的方法打包/拆分代碼,來較少HTTP請求數量。

Images

咱們可以看到的最後一個關於loader的例子是使用url-loader處理圖片。

在標準的HTML文檔中,當瀏覽器遇到一個<img>標籤或background-image屬性時會抓取圖片。使用webpack,當遇到小圖片的時候,你能夠經過將圖片源做爲字符串存儲在JavaScript中來優化小圖片,這樣,你預加載它們,瀏覽器就不用爲了提取它們而發起單獨的請求了。

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

添加一個加載圖片的規則:

// webpack.config.js
rules: [{
  test: /\.(png|jpg)$/,
  use: [{
    loader: 'url-loader',
    options: { limit: 10000 } // Convert images < 10k to base64 strings
  }]
}, {
  // ...
}]

從新運行項目:Ctrl + Cnpm start

使用下面命令下載test image

curl https://raw.githubusercontent.com/sitepoint-editors/webpack-demo/master/src/code.png --output src/code.png

你如今能夠在app.js的頭部導入圖片源:

// src/app.js
import codeURL from './code.png'
const img = document.createElement('img')
img.src = codeURL
img.style.backgroundColor = "#2B3A42"
img.style.padding = "20px"
img.width = 32
document.body.appendChild(img)

// ...

這將包括一張圖片,其中src屬性包含圖片自己的data URL:

<img src="data:image/png;base64,iVBO..." style="background: #2B3A42; padding: 20px" width="32">

此外,因爲使用url()引用的css-loader圖片也經過url-loader運行,這就好像直接在CSS中嵌入它們。

/* src/style.scss */
pre {
  background: $bluegrey url('code.png') no-repeat center center / 32px 32px;
}

編譯成爲:

pre {
    background: #2b3a42 url("data:image/png;base64,iVBO...") no-repeat scroll center center / 32px 32px;
}

Modules to Static Assets

你如今應該能夠看到loders是如何幫助在資源間創建一個依賴關係樹的,這是webpack首頁上的圖片展現:
圖片描述

儘管JavaScript是入口點,但webpack注意到你的其餘資源(如HTML、CSS和SVG)都具備各自的依賴關係——這些依賴關係是應該視爲構建過程的一部分的。

做者:Mark Brown
原文連接:A Beginner’s Guide to Webpack 2 and Module Bundling

相關文章
相關標籤/搜索