webpack基本使用

若是你的代碼不須要模塊化,那麼你不須要 webpack;若是你的代碼須要模塊化,那麼你可能須要 webpack;若是你的代碼裏,JavaScript、圖片、CSS、JSON 等等千奇百怪的文件都要模塊化,那麼你必定須要 webpack。javascript

爲何選擇 webpackcss

webpack 官網 是這樣定義 webpack 的:html

webpack is a module bundlerjava

什麼是 module?咱們首先會想到 JavaScript 的 ES 模塊、AMD 模塊,又或 Node.js 下的 CommonJS 模塊。node

只不過在 webpack 下,全部類型的文件均可以是模塊,包括 JavaScript、CSS、圖片、JSON。react

咱們固然知道在 JavaScript 裏 import/require 一張圖片會報錯。但在 webpack 下,這是容許的,這歸功於加載器(loader)。經過加載器,webpack 將 JavaScript 的模塊化推廣到其它類型文件 - 這正是 webpack 跨出的不同凡響的一步 - 但也致使它配置繁多,廣受詬病。jquery

但明白 webpack 這一用意,咱們就掌握了 webpack 核心,接下來的事,查查文檔基本都能搞定。webpack

React.js 項目git

我在這裏草擬了一個簡單的單頁面應用,頁面上有一張圖片,點擊圖片,圖片會旋轉,再次點擊則恢復原來的位置。github

接下來咱們將從零開始,用 webpack 搭建一個 React.js 開發環境,並完成編碼、打包、部署。

初始化項目

首先,咱們來初始化項目:

$ cd ~
$ mkdir -p tmp/webpack-demo && cd tmp/webpack-demo
$ npm init -y

項目初始化完成後,webpack-demo 目錄下多出 package.json 文件,內容以下:

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

新建 HTML

在 webpack-demo 下新建 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>webpack 教程</title> </head> <body> </body> </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>webpack 教程</title> </head> <body> </body> </html>

咱們暫時尚未引用 JavaScript。

建立 JavaScript 文件

在 webpack-demo 目錄下新建 index.js,內容暫時留空。

咱們須要安裝 react 及 react-dom

$ npm i react react-dom

裝好後,在 index.js 文件中 import 它們:

import React from 'react'
import ReactDOM from 'react-dom'

好了,如今在 index.html 中引用 index.js

 <body> + <script src="index.js"></script> </body> <body> + <script src="index.js"></script> </body>

如今在瀏覽器中打開 index.html,不出意外,console 中報錯了,只是不一樣瀏覽器下報的錯不同:

  1. Firefox 59.0.2: SyntaxError: import declarations may only appear at top level of a module
  2. Safari 11.0.3: SyntaxError: Unexpected identifier 'React'. import call expects exactly one argument.
  3. Chrome 65.0.3325.181: Uncaught SyntaxError: Unexpected identifier

怎麼辦?瀏覽器的兼容性問題幾乎是與生俱來的 - 要怎麼抹平它們的差異,好讓代碼可以運行在儘量多的瀏覽器平臺上?

咱們要用 webpack 來構建咱們的源代碼。

安裝 webpack

在 webpack-demo 項目根目錄中安裝 webpack

$ npm install -D webpack

安裝完成後,咱們就會看到當前安裝的 webpack 版本號。

編譯 JavaScript

webpack 是個打包工具,那麼就須要一個輸入(入口文件),一個輸出(目標文件)。

咱們試試在命令行下將 index.js 打包成 build.min.js

$ npx webpack index.js -o build.min.js
The CLI moved into a separate package: webpack-cli
Would you like to install webpack-cli? (That will run npm install -D webpack-cli) (yes/NO)

沒有打包,反而是提示咱們是否安裝 webpack-cli。這是由於 webpack 在 webpack 4 裏將命令行相關的都遷移至 webpack-cli 包。

輸入 yes 而後回車,稍等一下子,webpack-cli 就安裝好了。以後咱們的命令繼續執行,結果以下:

Hash: cbb2732def750315c477
Version: webpack 4.5.0
Time: 243ms
Built at: 2018-4-7 09:56:02
       Asset     Size  Chunks             Chunk Names
build.min.js  105 KiB       0  [emitted]  main
Entrypoint main = build.min.js
  [13] ./index.js 58 bytes {0} [built]
    + 13 hidden modules

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

打包成功,但出現黃色警告。這是 webpack 4 引入的模式,包括 developmentproductionnone 三個值,咱們不傳入值的話,默認使用 production

咱們來調整下命令:

$ npx webpack index.js -o build.min.js --mode development

再也不出現黃色警告了。

你可能好奇,不指定輸入、輸出的話會怎樣?

咱們來試試:

$ npx webpack --mode development
Hash: 86d52d22c7b7982a7ebf
Version: webpack 4.5.0
Time: 41ms
Built at: 2018-4-7 10:00:39

ERROR in Entry module not found: Error: Can't resolve './src' in '/Users/sam/tmp/webpack-demo'

報錯,說在 ./src 下找不到 index.js 文件 - 這也是 webpack 4 引入的約定,不指定輸入文件的話,則默認爲 src/index.js。咱們按照約定將項目根目錄下的 index.js 移動到 src/index.js

$ mkdir src
$ mv index.js src

而後再打包一遍:

$ npx webpack --mode development
Hash: 4726bc2e160759010056
Version: webpack 4.5.0
Time: 321ms
Built at: 2018-4-7 10:03:24
  Asset     Size  Chunks             Chunk Names
main.js  688 KiB    main  [emitted]  main
Entrypoint main = main.js
[./src/index.js] 58 bytes {main} [built]
    + 21 hidden modules

打包成功,且目錄下多出 dist/main.js - 這也正是 webpack 4 未指定輸出文件時默認的位置。也就是說,咱們按照 webpack 約定組織代碼文件的話,能夠省去許多配置。

打包完成後,咱們將 index.html 中對 JavaScript 引用調整爲編譯後的 dist/main.js

 <body> - <script src="./index.js"></script> + <script src="dist/main.js"></script> </body> <body> - <script src="./index.js"></script> + <script src="dist/main.js"></script> </body>

再刷新瀏覽器,控制檯已經再也不報錯。

但這樣的代碼結構在部署時十分不便,咱們除了要拷貝 dist 目錄外,還要從衆多文件中拷貝出 index.html 文件,從部署上說,只需拷貝一個目錄是最方便的,所以將 index.html 也移入 dist 目錄,順便清理 build.min.js 文件:

$ mv index.html dist
$ rm build.min.js

而後再調整 index.html 中的 js 引用:

 <body> - <script src="dist/main.js"></script> + <script src="main.js"></script> </body> <body> - <script src="dist/main.js"></script> + <script src="main.js"></script> </body>

實時刷新

在 index.html 文件中引用 main.js 文件後,咱們有幾個問題須要解決。

  1. 入口文件 src/index.js 的變化,包括它所引用的其它模塊的變化如何通知給 webpack,以便從新構建 dist/main.js 文件?
  2. dist/main.js 文件更新後,瀏覽器中打開的頁面該如何自動刷新?

監控文件

第一個問題,webpack 有好幾個解決辦法,其中 watch 選項最直觀,咱們可讓 webpack 監控文件變化,一旦文件有變化,就從新構建。但默認狀況下,watch 選項是禁用的。

咱們能夠在命令行下啓用它:

$ npx webpack --mode development --watch

Webpack is watching the files…

Hash: 4726bc2e160759010056
Version: webpack 4.5.0
Time: 367ms
Built at: 2018-4-7 10:12:59
  Asset     Size  Chunks             Chunk Names
main.js  688 KiB    main  [emitted]  main
Entrypoint main = main.js
[./src/index.js] 58 bytes {main} [built]
    + 21 hidden modules

咱們試試在 index.js 文件中添加一行 console.log('hello webpack'),保存文件後就會看到命令行下的變化:

Hash: 0d285ea4d1c26ac17380
Version: webpack 4.5.0
Time: 19ms
Built at: 2018-4-7 10:13:35
  Asset     Size  Chunks             Chunk Names
main.js  688 KiB    main  [emitted]  main
Entrypoint main = main.js
[./src/index.js] 87 bytes {main} [built]
    + 21 hidden modules

webpack 監控到 src/index.js 文件的變化,從新構建了 dist/main.js,耗時 19ms。

刷新瀏覽器

至於自動刷新瀏覽器的問題,webpack 提供 webpack-dev-server 來解決,它是一個基於 expressjs 的開發服務器,提供實時刷新瀏覽器頁面的功能。不過目前 webpack-dev-server 已經進入維護模式,文檔中推薦咱們使用 webpack-serve

但這裏暫時仍是使用 webpack-dev-server 來講明。

webpack-dev-server

首先在項目下安裝 webpack-dev-server

$ npm install -D webpack-dev-server

安裝完成後在命令行下執行 webpack-dev-server

$ npx webpack-dev-server --mode development --content-base ./dist
ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: Content not from webpack is served from /Users/sam/tmp/webpack-demo/dist
ℹ 「wdm」: Hash: 441c738298078bd7a80b
Version: webpack 4.5.0
Time: 508ms
Built at: 2018-4-13 19:52:45
  Asset      Size  Chunks             Chunk Names
main.js  1020 KiB    main  [emitted]  main
Entrypoint main = main.js
[./node_modules/ansi-html/index.js] 4.16 KiB {main} [built]
[./node_modules/loglevel/lib/loglevel.js] 7.68 KiB {main} [built]
[./node_modules/react-dom/index.js] 1.33 KiB {main} [built]
[./node_modules/react/index.js] 190 bytes {main} [built]
[./node_modules/sockjs-client/dist/sockjs.js] 176 KiB {main} [built]
[./node_modules/url/url.js] 22.8 KiB {main} [built]
[./node_modules/webpack-dev-server/client/index.js?http://localhost:8080] (webpack)-dev-server/client?http://localhost:8080 7.75 KiB {main} [built]
[./node_modules/webpack-dev-server/client/overlay.js] (webpack)-dev-server/client/overlay.js 3.58 KiB {main} [built]
[./node_modules/webpack-dev-server/client/socket.js](webpack)-dev-server/client/socket.js 1.05 KiB {main} [built]
[./node_modules/webpack-dev-server/node_modules/strip-ansi/index.js] (webpack)-dev-server/node_modules/strip-ansi/index.js 161 bytes {main} [built]
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
[./node_modules/webpack/hot/emitter.js] (webpack)/hot/emitter.js 77 bytes {main} [built]
   [0] multi (webpack)-dev-server/client?http://localhost:8080 ./src 40 bytes {main} [built]
[./node_modules/webpack/hot/log.js] (webpack)/hot/log.js 1.03 KiB {main} [optional] [built]
[./src/index.js] 87 bytes {main} [built]
    + 32 hidden modules
ℹ 「wdm」: Compiled successfully.

Ooops,使人暈眩的輸出結果。

不過且忽視它們,咱們如今能夠在 http://localhost:8080/ 訪問咱們的 index.html

在入口文件 src/index.js 裏再添加一行代碼驗證下瀏覽器頁面的實時刷新功能:

console.log('webpack live reload is working')

webpack 從新打包了 dist/main.js,瀏覽器中打開的頁面同時也刷新了。實際上,咱們看 webpack-dev-server 的命令行會發現,它一樣監控入口文件的變化並從新編譯 - 換句話說,webpack-dev-server 已經啓用 --watch 效果。

編碼

咱們在 src/index.js 中先寫個簡單的 React 代碼:

import React from 'react'
-import ReactDOM from 'react-dom'
+import ReactDOM from 'react-dom'
+ReactDOM.render(<div>hello webpack</div>, document.body)

注意,React 不推薦使用 body 上,這裏只是圖方便才這麼寫。

查看 webpack-dev-server 的狀態:

[./src/index.js] 255 bytes {main} [built] [failed][1 error]
    + 25 hidden modules

ERROR in ./src/index.js
Module parse failed: Unexpected token (3:16)
You may need an appropriate loader to handle this file type.
| import React from 'react'
| import ReactDOM from 'react-dom'
| ReactDOM.render(<div>hello webpack</div>, document.body)
|
 @ multi (webpack)-dev-server/client?http://localhost:8080 ./src
ℹ 「wdm」: Failed to compile.

報錯。爲何?由於咱們寫了 JSX 語法,webpack 不認識。怎麼辦,找 babel-loader 來翻譯。

$ npm install -D "babel-loader@^8.0.0-beta" @babel/core @babel/preset-react

接着重啓 webpack-dev-server:

$ npx webpack-dev-server --mode development --content-base ./dist --module-bind 'js=babel-loader?presets[]=@babel/preset-react'

再也不報錯,且頁面上已經顯示 hello webpack

webpack 配置文件

隨着咱們配置的插件愈來愈多,命令行會愈來愈長,這時,咱們能夠將命令行參數移入 webpack 配置文件。

咱們來新建一個 webpack.config.js 文件:

const path = require('path')
module.exports = {
  mode: 'development',
  devServer: {
    contentBase: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        include: [
          path.resolve(__dirname, 'src')
        ],
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-react']
        }
      }
    ]
  }
}

這樣,咱們只要執行 npx webpack-dev-server 就行,再也不須要輸入一長串命令行。

圖片加載器

咱們須要一張圖片,我從 unsplash 找來了一張玫瑰,放到 src/img/rose.jpg 位置。

咱們在 src/index.js 中 import 它:

import ReactDOM from 'react-dom'
+import Rose from './img/rose.jpg'
 ReactDOM.render(<div>hello webpack</div>, document.body)

不出意外,報錯了:

[./src/img/rose.jpg] 177 bytes {main} [built] [failed] [1 error]
[./src/index.js] 178 bytes {main} [built]
    + 46 hidden modules

ERROR in ./src/img/rose.jpg
Module parse failed: Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
 @ ./src/index.js 3:0-34
 @ multi (webpack)-dev-server/client?http://localhost:8080 ./src
ℹ 「wdm」: Failed to compile.

和處理 JSX 一個道理,咱們須要翻譯(即加載器)。

在 webpack 裏,負責圖片翻譯的是 file-loader

$ npm install -D file-loader

接着是配置 webpack.config.js

+      },
+      {
+        test: /\.(png|jpg|gif)$/,
+        use: [
+          {
+            loader: 'file-loader',
+            options: {}
+          }
+        ]
       }
     ]

重啓 webpack-dev-server,發現 webpack 已經能正常編譯了 - 圖片搖身一變,也是一個模塊。

並且,webpack 在最終構建時,會自動將模塊中引用的圖片拷貝到相應目錄 - 謝天謝地,不再用手動拷貝。

確保圖片加載沒問題後,咱們來完善下代碼:

-ReactDOM.render(<div>hello webpack</div>, document.body)
+class App extends React.Component {
+  render () {
+    return (
+      <div><img src={Rose} alt='玫瑰' /></div>
+    )
+  }
+}
+ReactDOM.render(<App />, document.body)

查看瀏覽器,圖片已經渲染出來 - 可是圖片太大了。咱們須要 CSS 來控制圖片尺寸。

加載 CSS 文件

在 React.js 裏,CSS 有不少種寫法,好比咱們能夠直接寫在 style 中:

<img src={Rose} alt='玫瑰' style={{maxWidth: 500}} /> <img src={Rose} alt='玫瑰' style={{maxWidth: 500}} />

由於這就是 JavaScript,咱們也就不須要額外處理。

但咱們也能夠寫在 css 文件中。

在 src 下新增 index.css

.flower { max-width: 500px; } .flower { max-width: 500px; }

而後在 index.js 中引入並應用:

import React from 'react'
 import ReactDOM from 'react-dom'
 import Rose from './img/rose.jpg'
+import './index.css'
 class App extends React.Component {
   render () {
     return (
-      <div><img src={Rose} alt='玫瑰' /></div>
+      <div><img src={Rose} alt='玫瑰' className='flower' /></div>
     )
   }
 }

但 webpack-dev-server 又報錯了:

[./src/index.css] 166 bytes {main} [built] [failed] [1 error]
[./src/index.js] 391 bytes {main} [built]
    + 47 hidden modules

ERROR in ./src/index.css
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
| .flower {
|   max-width: 500px;
| }
 @ ./src/index.js 4:0-21
 @ multi (webpack)-dev-server/client?http://localhost:8080 ./src
ℹ 「wdm」: Failed to compile.

一樣的,咱們須要 CSS 加載器:

  1. css-loader - 預處理 CSS 文件
  2. style-loader - 將 CSS 插入到 DOM 中的 style 標籤

注意,咱們若是隻使用了 css-loader,則 webpack 只是將 CSS 文件預處理成模塊而後打包到構建文件中,並不會插入到頁面 - 這是 style-loader 的做用。

咱們先來安裝它們:

$ npm install -D css-loader style-loader

而後修改 webpack.config.js 配置:

+      },
+      {
+        test: /\.css$/,
+        use: [{ loader: 'style-loader' }, { loader: 'css-loader' }]
       }
     ]
   }

請注意,loader 的順序很重要,好比上面新增的這一節,若是把 style-loader 放到 css-loader 後面,咱們就會撞見錯誤:

ERROR in ./index.css
Module build failed: Unknown word (5:1)

  3 | // load the styles
  4 | var content = require("!!./index.css");
> 5 | if(typeof content === 'string') content = [[module.id, content, '']];
    | ^
  6 | // Prepare cssTransformation
  7 | var transform;
  8 |

 @ ./index.js 3:0-21
 @ multi (webpack)-dev-server/client?http://localhost:8080 ./index.js
webpack: Failed to compile

由於 style-loader 沒法理解 CSS 文件,須要先經 css-loader 預處理 - 是的,加載器的執行順序是從後往前的。

重啓 webpack-dev-server,編譯正常,css 已生效。

只不過,這裏的 CSS 雖然是 import 進來的,但還是全局的,等效於咱們日常使用 <link href="" /> 引用 CSS。webpack 還提供 CSS Modules,能夠將樣式真正意義上的模塊化。

除了 CSS Modules 外,咱們還有不少 CSS in js 方案可選,它們容許咱們將樣式跟 HTML、JS 放到一塊兒 - 若是你寫過 Vue.js 的單文件模塊,可能會很喜歡。

在成功配置圖片與 CSS 後,咱們能夠繼續完善代碼:

src/index.css

+} +.flower--rotate { + transform: rotate(30deg); } +} +.flower--rotate { + transform: rotate(30deg); }

src/index.js

class App extends React.Component {
+  state = {
+    reset: 'yes'
+  }
+  onClick = () => {
+    this.setState({
+      reset: this.state.reset === 'yes' ? 'no' : 'yes'
+    })
+  }
   render () {
     return (
-      <div><img src={Rose} alt='玫瑰' className='flower' /></div>
+      <div><img src={Rose} alt='玫瑰' className={this.state.reset === 'yes' ? 'flower' : 'flower flower--rotate'} onClick={this.onClick} /></div>
     )
   }
 }

但隨即發現 webpack-dev-server 又拋出錯誤:

[./src/index.js] 1.49 KiB {main} [built] [failed] [1 error]
    + 25 hidden modules

ERROR in ./src/index.js
Module build failed: SyntaxError: /Users/sam/tmp/webpack-demo/src/index.js: Support for the experimental syntax 'classProperties' isn't currently enabled (6:9):

  4 | import './index.css'
  5 | class App extends React.Component {
> 6 |   state = {
    |         ^
  7 |     reset: 'yes'
  8 |   }
  9 |   onClick = () => {

Add @babel/plugin-proposal-class-properties (https://git.io/vb4SL) to the 'plugins' section of your Babel config to enable transformation.
    at _class.raise (/Users/sam/tmp/webpack-demo/node_modules/babylon/lib/index.js:779:15)
    at _class.expectPlugin (/Users/sam/tmp/webpack-demo/node_modules/babylon/lib/index.js:2087:18)
    at _class.parseClassProperty (/Users/sam/tmp/webpack-demo/node_modules/babylon/lib/index.js:4904:12)
    at _class.pushClassProperty (/Users/sam/tmp/webpack-demo/node_modules/babylon/lib/index.js:4871:30)
    at _class.parseClassMemberWithIsStatic (/Users/sam/tmp/webpack-demo/node_modules/babylon/lib/index.js:4804:14)
    at _class.parseClassMember (/Users/sam/tmp/webpack-demo/node_modules/babylon/lib/index.js:4741:10)
    at _class.parseClassBody (/Users/sam/tmp/webpack-demo/node_modules/babylon/lib/index.js:4696:12)
    at _class.parseClass (/Users/sam/tmp/webpack-demo/node_modules/babylon/lib/index.js:4646:10)
    at _class.parseStatementContent (/Users/sam/tmp/webpack-demo/node_modules/babylon/lib/index.js:3987:21)
    at _class.parseStatement (/Users/sam/tmp/webpack-demo/node_modules/babylon/lib/index.js:3959:17)
 @ multi (webpack)-dev-server/client?http://localhost:8080 ./src
ℹ 「wdm」: Failed to compile.

這是由於咱們用了 JavaScript 的新特性 - 須要 @babel/plugin-proposal-class-properties 插件的支持。

首先是安裝該插件:

$ npm i -D @babel/plugin-proposal-class-properties

而後調整 webpack.config.js 配置:

options: {
           presets: ['@babel/preset-react']
+          plugins: ['@babel/plugin-proposal-class-properties']
         }
       },

重啓 webpack-dev-server,編譯正常。

查看瀏覽器,圖片已經能夠點擊了。

打包

在完成項目開發後,咱們須要輸出文件給生產環境部署,只要執行:

$ npx webpack --mode production

就能夠打包出全部靜態資源。

部署

部署時,拷貝 dist 目錄便可。

清理 dist

隨着某些文件的增刪,咱們的 dist 目錄下會產生一些再也不使用的文件,咱們不想這些文件也部署到生產環境上佔用空間,因此 webpack 在打包前最好能刪除 dist 目錄。

咱們來試試 clean-webpack-plugin

首先是安裝:

$ npm i -D clean-webpack-plugin

而後在 webpack.config.js 中調用:

const path = require('path')
+const CleanWebpackPlugin = require('clean-webpack-plugin')
 module.exports = {
   mode: 'development',
   devServer: {
     contentBase: path.resolve(__dirname, 'dist')
   },
+  plugins: [
+    new CleanWebpackPlugin(['dist'])
+  ],
   module: {

再執行 npx webpack --mode production,webpack 確實會在打包前清空 dist 目錄,但咱們的 index.html 也一塊兒被清空了。

html-webpack-plugin

咱們使用 html-webpack-plugin 來自動生成 index.html

首先是安裝:

$ npm i --save-dev html-webpack-plugin

調整 webpack.config.js

const CleanWebpackPlugin = require('clean-webpack-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
 module.exports = {
   mode: 'development',
   devServer: {
     contentBase: path.resolve(__dirname, 'dist')
   },
   plugins: [
-    new CleanWebpackPlugin(['dist'])
+    new CleanWebpackPlugin(['dist']),
+    new HtmlWebpackPlugin()
   ],

再運行 npx webpack --mode productiondist 下已經自動生成 index.html,再 title 倒是 Webpack App,咱們須要再調整一下 webpack.config.js

plugins: [
     new CleanWebpackPlugin(['dist']),
-    new HtmlWebpackPlugin()
+    new HtmlWebpackPlugin({
+      title: 'webpack 教程'
+    })
   ],

腳手架

前面的步驟裏,咱們幾乎是一步、一步手動配置每一個類型文件的加載器,一次添加一小節,而後重啓 webpack-dev-server,恐怕沒人喜歡這樣幹活。因此市面上有很是多的 boilerplates、presets 等,其中比較出名的有:

  1. create-react-app react 官方出品的一套,只適用開發 react.js 項目;
  2. neutrino.js 這是 Mozilla 出品的一套解決方案,Web、React、Node.js 等方案均有;
  3. Parcel 最近新出的一套方案,零配置。

博主在這裏就不詳細介紹webpack來源以及做用了, 本篇博文面向新手主要說明如何配置webpack, 以及webpack的使用方法, 直到建立出一個合理的屬於本身webpack項目;

流程

webpack安裝

  • Step 1: 首先安裝Node.js, 能夠去Node.js官網下載.

  • Step2: 在Git或者cmd中輸入下面這段代碼, 經過全局先將webpack指令安裝進電腦中
    npm install webpack -g

  • Step3: 使用Git Bash here 或者 cmd cd命令使當前目錄轉到當前項目的目錄下, 而後輸入下面這段命令
    npm init
    這裏寫圖片描述
    接下來會彈出一些信息, 就是一些項目名和一些參數的描述, 能夠所有按回車使用默認信息, 完成以後項目文件夾下會生成一個package.json的文件
    這裏寫圖片描述
    這樣webpack就安裝完成了.




webpack配置

  • Step1: 建立項目文件夾, 名字自起, 但路徑名不要包含中文, 以及項目名也不要叫」webpack」, 而且不要包含大寫字母.
    例:這裏寫圖片描述
  • Step2: 接下來建立並編寫配置文件. 首先咱們先介紹幾個配置文件的參數. 
    • entry: 是 頁面入口文件配置 (html文件引入惟一的js 文件)
    • output:對應輸出項配置 
      • path :入口文件最終要輸出到哪裏,
      • filename:輸出文件的名稱
      • publicPath:公共資源路徑
  • Step3: 在你的項目目錄下建立webpack.config.js配置文件, 經過這個文件進行webpack的配置, 而且還要建立一些路徑保存基本文件. 例如: 
    這裏寫圖片描述
    src文件夾
    這裏寫圖片描述
  • Step4: 在src的js下建立一個入口文件, 我建立的叫作entry.js, 在項目目錄再建立一個index.html用來調試使用. 編寫webpack.config.js文件,

    //webpack.config.js
    module.exports = {
        entry : './src/js/entry.js',//入口文件
        output : {//輸出文件
            filename : 'index.js',//輸出文件名
            path : __dirname + '/out'//輸出文件路徑
        },
    }
    • 咱們隨便在index.html和入口文件entry.js寫點什麼看看是否成功配置,
    //index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>ss</title>
    </head>
    <body>
    111
        <script src="./out/index.js"></script>//注意在這裏引入的是打包完成的js文件
    </body>
    </html>
    //entry.js
    console.log('1234');

    以後使用Git Bash here 或者 cmd cd命令使目錄爲當前項目目錄, 輸入webpack或者webpack -w命令, 查看index.html是否成功console出1234;

webpack 和 webpack -w 區別 
webpack -w能夠對項目打包而且實時監控, 當前配置文件下的文件若是發生更改時從新打包, 但若是webpack的配置文件即webpack.config.js更改時仍是要經過webpack進行打包.(退出webpack -w 操做 ctrl+c)


 webpack loader加載器

接下來咱們繼續配置loader, 經過加載器處理文件:好比 sass less 等, 告知 webpack 每一種文件都須要使用什麼加載器來處理。

  • Step1: 爲了方便咱們先統一把全部的包都先下載下來, 下面再慢慢解釋.

    npm install babel-loader babel babel-core css-loader style-loader  url-loader file-loader less-loader less  --save-dev

  • Step2: 下載完成後, 咱們修改webpack.config.js文件, 將加載器引入.

    module.exports = {
        entry :  './src/js/entry.js',
        output : {
            filename : 'index.js',
            path : __dirname + '/out'
        },
        module : {
            rules: [
                {test: /.js$/, use: ['babel-loader']},
                {test: /.css$/, use: ['style-loader', 'css-loader']},/*解析css, 並把css添加到html的style標籤裏*/
                //{test: /.css$/, use: ExtractTextPlugin.extract({fallback: 'style-loader',use: 'css-loader'})},/*解析css, 並把css變成文件經過link標籤引入*/
                {test: /.(jpg|png|gif|svg)$/, use: ['url-loader?limit=8192&name=./[name].[ext]']},/*解析圖片*/
                {test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader']}/*解析less, 把less解析成瀏覽器能夠識別的css語言*/
            ]
        },
        }
  • Step3: 接下來咱們先測試css, 咱們在項目文件夾下的src文件夾下建立index.css. 隨便寫一點屬性. 

    //index.css
    .demo1 { width: 100px; height: 100px; background: red; }
    .demo2 { width: 200px; height: 200px; background: orange; }
    //index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8" />
    <title>text</title>
    </head>
    <body>
    <div class="demo1"></div>
    <div class="demo2"></div>
    <script src="./out/index.js"></script>
    </body>
    </html>

    由於在webpack中全部文件都是模塊, 因此必需要將css引入. 在剛剛的entry.js中添加以下代碼.

    //entry.js
    require('../css/index.css');//引入css文件
    console.log("1234");

    打包webpack一下看看效果 
    這裏寫圖片描述

  • Step4: 當有多個js文件時, 如何進行引入呢? 接下來咱們作一個簡單小功能來講明這個問題, 讓咱們點擊方塊的時候, 方塊變大.

    接下來在src的js文件夾下建立一個基本的工具tool.js (不少小的問題都被我擴大化了, 只是爲了說明問題不必定適用)

    //tool.js
    var tool = {//獲取DOM元素
        getDom: function(className) {
            return document.getElementsByClassName(className)[0];
        }
    }
    
    module.exports = tool;//模塊出口

    src的js下建立一個demo1.js文件, demo2.js同理

    var obj = require('./tool.js');
        var demo1 = {
        init: function() {
            this.bindEvent();
        },
        bindEvent: function() {
            //var demo1 = document.getElementsByClassName('demo1')[0];
            var demo1 = obj.getDom('demo1');
            demo1.onclick = this.changeStyle;
        },
        changeStyle: function() {
            this.style.width = '200px';
            this.style.height = '200px';
            this.style.background = 'green';
            console.log('1');
        }
    }
    
    module.exports = demo1;

    修改入口文件entry.js

    require('../css/index.css');
    
    var demo1 = require('../js/demo1.js');
    var demo2 = require('../js/demo2.js');
    
        demo1.init();
        demo2.init();

    webpack一下, 看看效果 
    這裏寫圖片描述



關於圖片的打包

  • Step1: 在img文件夾下隨便找一個小一點的圖片放進去.
  • Step2: 修改entry.js

    require('../css/index.css');
    
    var demo1 = require('../js/demo1.js');
    var demo2 = require('../js/demo2.js');
    
        demo1.init();
        demo2.init();
    
    var oImg = new Image();
    oImg.src = require('../img/1.gif');//當成模塊引入圖片
    document.body.appendChild(oImg);

    因爲咱們引入的是靜態資源, 在webpack.config.js中修改一下

    module.exports = {
            entry :  './src/js/entry.js',
            output : {
                filename : 'index.js',
                publicPath: __dirname + '/out',//添加靜態資源, 不然會出現路徑錯誤
                path : __dirname + '/out'
            },
            module : {
                rules: [
                    {test: /.js$/, use: ['babel-loader']},
                    {test: /.css$/, use: ['style-loader', 'css-loader']},/*解析css, 並把css添加到html的style標籤裏*/
                    //{test: /.css$/, use: ExtractTextPlugin.extract({fallback: 'style-loader',use: 'css-loader'})},/*解析css, 並把css變成文件經過link標籤引入*/
                    {test: /.(jpg|png|gif|svg)$/, use: ['url-loader?limit=8192&name=./[name].[ext]']},/*解析圖片*/
                    {test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader']}/*解析less, 把less解析成瀏覽器能夠識別的css語言*/
                ]
            },
    }

    你們本身webpack看看效果



webpack進階設定

咱們在項目中有多個html文件時怎麼處理呢?, 接下來咱們從新設定配置文件, webpack.config.js

module.exports = {
            entry : {index1: './src/js/entry.js', index2: './src/js/entry2.js'},
        output : {
                filename : '[name].js',//這樣就能夠生成兩個js文件, 名字分別爲index1.js, 和index2.js
                publicPath: __dirname + '/out',//添加靜態資源, 不然會出現路徑錯誤
                path : __dirname + '/out'
            },
            module : {
                rules: [
                    {test: /.js$/, use: ['babel-loader']},
                    {test: /.css$/, use: ['style-loader', 'css-loader']},/*解析css, 並把css添加到html的style標籤裏*/
                    //{test: /.css$/, use: ExtractTextPlugin.extract({fallback: 'style-loader',use: 'css-loader'})},/*解析css, 並把css變成文件經過link標籤引入*/
                    {test: /.(jpg|png|gif|svg)$/, use: ['url-loader?limit=8192&name=./[name].[ext]']},/*解析圖片*/
                    {test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader']}/*解析less, 把less解析成瀏覽器能夠識別的css語言*/
                ]
            },
    }



webpack插件使用

首先咱們因爲要使用webpack插件, 所以咱們要從新下載一下webpack包, 將目錄定位到當前項目目錄, 輸入npm install webpack 
以後咱們修改webpack.config.js, 將下面代碼放到配置文件開頭. 這樣就可使用插件了

var webpack = require('webpack');
  • 1

將插件信息寫到配置文件裏

var webpack = require('webpack');
var uglifyPlugin = new webpack.optimize.UglifyJsPlugin({minimize: true});//代碼壓縮

var CommonsChunkPlugin = new webpack.optimize.CommonsChunkPlugin('common');//把公共模塊提取出來, 並取名爲'common'(名字自起), webpack以後再out文件夾下生成common.js, 測試時記得引入提取出來的公共模塊js文件

var ExtractTextPlugin = require("extract-text-webpack-plugin");//將css獨立引入變成link標籤形式, 使用該插件須要獨立下載'npm install extract-text-webpack-plugin --save-dev', 同時下面的rules也必須更改

var providePlugin = new webpack.ProvidePlugin({$: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery'});//引入jquery



module.exports = {
    entry : {index: './src/js/entry.js', index2: './src/js/entry2.js'},
    output : {
        filename : '[name].js',
        publicPath: __dirname + '/out',
        path : __dirname + '/out'
    },
    module : {
        rules: [
            {test: /.js$/, use: ['babel-loader']},
            //{test: /.css$/, use: ['style-loader', 'css-loader']},
            {test: /.css$/, use: ExtractTextPlugin.extract({fallback: 'style-loader',use: 'css-loader'})},
            {test: /.(jpg|png|gif|svg)$/, use: ['url-loader?limit=8192&name=./[name].[ext]']},
            {test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader']}
        ]
    },
    plugins: [uglifyPlugin, CommonsChunkPlugin, new ExtractTextPlugin('[name].css'),providePlugin]//插件集合
}

webpack服務器

首先先定位目錄輸入命令 npm install webpack-dev-server -g 
, 修改webpack.config.js文件

publicPath: 'http://localhost:8080/out',
  • 1

html文件所引用的目錄也要更改:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>text</title>
     <link rel="stylesheet" href="http://localhost:8080/out/index.css">
</head>
<body>
    <a href="http://localhost:8080/index2.html">11</a>
    <div class="demo1"></div>
    <div class="demo2"></div>
    <script src="http://localhost:8080/out/common.js"></script>
    <script src="http://localhost:8080/out/index.js"></script>
</body>
</html>
  • webpack-dev-server一下看看效果

小工具: webpace-dev-server –devtool eval-source-map –progess –colors打包時輸入這一行能夠直接找到文件若是出錯時的位置

小知識點: 上面這一句話若是以爲太長能夠將

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "xuan": "webpack-dev-server --devtool eval-source-map --progress --colors"
  },

這一段代碼放到項目目錄下的package.json裏, 這樣調試時若是輸入npm run xuan就等於輸入那一長串代碼

相關文章
相關標籤/搜索