深入淺出 Webpack【閱讀總結】章節一

前言 - 閱讀《深入淺出webpack》一書實踐記錄一

目錄

  • 安裝與使用
  • Loader
  • Plugin
  • Devserver

源碼參考

安裝與使用

# npm i -D 是 npm install --save-dev 的簡寫,
--save 是指安裝模塊並保存到 package.json 的 devDependencies

# 安裝最新穩定版
npm i -D webpack

# 安裝指定版本
npm i -D webpack@<version>

# 安裝最新體驗版本
npm i -D webpack@beta

# 全局安裝
npm i -g webpack

下面通過 Webpack 構建一個基於 CommonJS 模塊化編寫的項目,該項目會使用JavaScript通過webpack編譯在網頁中顯示 Hello,Webpack。

創建一個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>Document</title>
  <!--引入 Webpack 輸出的 JavaScript 文件暫時命名 bundle.js -->
  <script src="./dist/bundle.js"></script>
</head>

<body>
  <div id="app"></div>
</body>

</html>

創建一個執行入口文件 main.js

var showText = require("./utils.js");
showText('Webpack');

main.js 裏邊的代碼很簡單,就是 require 導入一個模塊兒 utils.js 在commonJs模塊兒規範裏邊一個Js文件就相當於一個模塊兒,緊跟着就是調用這個模塊兒裏的函數;好,那麼此時我需要創建這個模塊兒文件utils.js

創建utils.js

// 操作 DOM 元素,把 content 顯示到網頁上
function showText(content) {
  window.document.getElementById('app').innerText = 'Hello,' + content;
}
// 通過 CommonJS 規範導出 show 函數
module.exports = showText;

內容也很簡單就是一個函數 showText ,函數體就是在頁面顯示一段文本,緊跟着後邊就是導出這個函數。

好,入口文件以及執行的操作都有了,接下來我們需要一個webpack配置文件,緊接着,我們再創建一個webpack.config.js 文件

創建webpack.config.js

const path = require('path');
module.exports = {
  entry: './main.js', // 入口文件,很重要,運行webpack構建唯一執行的文件
  output: {
    // 把所有依賴的模塊合併輸出到一個 bundle.js 文件
    filename: 'bundle.js',
    // 輸出文件都放到 dist 目錄下
    // __dirname 只當前指向目錄
    path: path.resolve(__dirname, './dist'),
  }
};

內容其實也很少啊,我們簡單分析一下,path 基於node模塊的path模塊兒,主要就是路徑(顧名思義啊),然後就是導出一個對象,這個對象裏邊包含了入口文件和出口文件配置;具體的解釋都寫在代碼註釋了。

截至到這裏,我們的準備文件都已經就緒了,目錄暫時如下:

webpack // 工程目錄
	index.html
	main.js
	utils.js
	webpack.config.js

看到這裏,小夥伴們是不是感覺還差點什麼,對,package.json 文件,那麼我們初始化一下
npm install , 會發現命令行裏會讓我們填寫一些東西,例如:webpack項目名字,作者,版本,入口文件等等。我們一一確認一下就好。
在這裏插入圖片描述
package.json 文件,我們需要在 scripts 對象裏新增一條執行命令,執行我們的
webpack 配置文件,也就是 webpack.config.js文件

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "HiSen",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    // 新增命令
    "build":"webpack --config webpack.config.js"
  },
  "author": "",
  "license": "ISC"
}

準備就緒了,我們安裝 webpack npm install -D webpack , 然後執行我們的webpack構建命令 npm run build 其實就是執行的 "webpack --config webpack.config.js" 看上邊的scripts對象。結果不盡人意啊(如下圖示),還讓我們安裝 webpack-cli 理由既然是作爲單獨的包提供,好吧,照着來吧。
在這裏插入圖片描述
這裏有一個小插曲,選擇 yes 安裝居然會報錯,我沒有去查看到底是因爲什麼啊,我直接自己命令裝了一下
在這裏插入圖片描述
好了,這一下算是全部文件準備就緒了,此時我們的目錄和package.json文件都發生了一點點小小的改變;如下:

webpack  // 工程目錄
	index.html
	main.js
	utils.js
	webpack.config.js
	package.json
	node_modules

目錄在安裝webpack的時候會自動生成一個依賴文件,node_modules
在這裏插入圖片描述
package.json文件 devDependencies 對象也增加了我們安裝的 webpackwebpack-cli

最後,我們來嘗試構建打包一下:npm run build
在這裏插入圖片描述
恭喜你 ,結果很明顯,成功了,我們簡單的實現了一個webpack構建打包的實例。

代碼結構目錄

webpack  // 工程目錄
	dist // 構建生成目錄
	   bundle.js
	index.html
	main.js
	utils.js
	webpack.config.js
	package.json
	node_modules

打開本地的HTML就可以看到,我們的頁面,可能會遇到一個小小的錯誤
Cannot set property 'innerText' of null
因爲JavaScript運行時,id="app"的那個div元素可能還沒解析和加載,只需把整個搬到前面即可,就像這樣:在這裏插入圖片描述
最後結果:
在這裏插入圖片描述

Loader

很重的一個知識點,接下來我們能創建一個css文件 main.css,然後同樣在我們的入口文件main.js 文件引入,結果如下:

main.css文件內容

#app{
  text-align: center;
  color:red;
}

main.js 導入

require("./main.css"); // 導入main.css 文件
var showText = require("./utils.js");
showText('Webpack');

顯然這樣直接構建,Webpack 構建是會報錯的,因爲 Webpack 不原生支持解析 CSS 文件。要支持非 JavaScript 類型的文件,需要使用 Webpack 的 Loader 機制。所以我們修改webpack.config.js 文件,添加 Loader 配置(Loader 可以理解爲是文件解析器,解析類似 css,less,scss等)

module.exports = {

  entry: './main.js', // 入口文件
  output: {
    // 把所有依賴的模塊合併輸出到一個 bundle.js 文件
    filename: 'bundle.js',
    // 輸出文件都放到 dist 目錄下
    // __dirname 只當前指向目錄
    path: path.resolve(__dirname, './dist'),
  },
  // 添加如下配置
  module: {
    rules: [
      {
        test: /\.css$/, // 用正則去匹配要用該 loader 轉換的 CSS 文件
        use: ['style-loader', 'css-loader'] // 注意這裏順序不能錯
      }
    ]
  }
};

user 還有另外一種寫法,數組對象形式

use: [
 'style-loader', 
  {
    loader:'css-loader',
    options:{
      minimize:true, // minimize 告訴 css-loader 要開啓 CSS 壓縮。
    }
  }
]

配置裏的 module.rules 數組配置了一組規則,告訴 Webpack 在遇到哪些文件時使用哪些 Loader 去加載和轉換。

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

注意:
use 屬性的值需要是一個由 Loader 名稱組成的數組,Loader 的執行順序是由後到前的; 每一個 Loader 都可以通過 URL querystring (或者數組對象)的方式傳入參數。

好,接下來,我們來實踐一下,在構建之前,首先需要安裝 Loader,在這裏使用到了 style-loader,css-loader ,安裝一下

npm i -D style-loader css-loader

package.json 文件會顯示出來,後續大家請自己關注,我就不貼圖了。
在這裏插入圖片描述
效果如下
在這裏插入圖片描述

你會發現 bundle.js 文件被更新了,裏面注入了在 main.css 中寫的 CSS,而不是會額外生成一個 CSS 文件。 但是重新刷新 index.html 網頁時將會發現 Hello,Webpack 居中了,樣式生效了! 也許你會對此感到奇怪,第一次看到 CSS 被寫在了 JavaScript 裏!這其實都是 style-loader 的功勞,它的工作原理大概是把 CSS 內容用 JavaScript 裏的字符串存儲起來, 在網頁執行 JavaScript 時通過 DOM 操作動態地往 HTML head 標籤裏插入 HTML style 標籤。 也許你認爲這樣做會導致 JavaScript 文件變大並導致加載網頁時間變長,想讓 Webpack 單獨輸出 CSS 文件。接着往下看

Plugin

首先我們需要下載插件 extract-text-webpack-plugin

npm i -D extract-text-webpack-plugin

然後直接看向 webpack.config.js 配置文件,進行如下配置:

1,引入extract-text-webpack-plugin 插件, 作用是提取出 JavaScript 代碼裏的 CSS 到一個單獨的文件
2,module 裏添加 plugin 數組,通過插件的 filename 屬性,告訴插件輸出的 CSS 文件名稱是通過 [name]_[contenthash:8].css 字符串模版生成的,裏面的[name]代表文件名稱,[contenthash:8] 代表根據文件內容算出的8位 hash 值,
3,修改rules 裏邊use ,使用ExtractTextPlugin 插件轉換 css-loader,這裏不需要再使用style-loader解析了。

const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin'); // 引入 plugin 插件 

module.exports = {

  entry: './main.js', // 入口文件
  output: {
    // 把所有依賴的模塊合併輸出到一個 bundle.js 文件
    filename: 'bundle.js',
    // 輸出文件都放到 dist 目錄下
    // __dirname 只當前指向目錄
    path: path.resolve(__dirname, './dist'),
  },
  // 添加如下配置
  module: {
    rules: [
      {
        // 用正則去匹配要用該 loader 轉換的 CSS 文件
        test: /\.css$/,
        // use: ['style-loader', 'css-loader'],
        use: ExtractTextPlugin.extract({
          // 轉換 .css 文件需要使用的 Loader
          use: ['css-loader']
        }),
      }
    ]
  },

  plugins: [
    new ExtractTextPlugin({
      // 從 .js 文件中提取出來的 .css 文件的名稱
      filename: `[name]_[contenthash:8].css`,
    }),
  ]
};

以上修改完成後,我們開始構建,索嘎,成功的構建出來了,如果發現報錯,請檢查webpack版本和ExtractTextPlugin版本是否匹配。

構建出來的 dist 目錄如下:

dist
	bundle.js // js 裏邊也不含有 css 樣式代碼了
	main_69bba57c.css // 而這個css文件就是我們的 main.css 文件

DevServer

前面的幾節只是讓 Webpack 正常運行起來了,但在實際開發中你可能會需要:

1,提供 HTTP 服務而不是使用本地文件預覽;
2,監聽文件的變化並自動刷新網頁,做到實時預覽;
3,支持 Source Map,以方便調試。

當然這些 webpack 都爲你想好了,DevServer會啓動一個 HTTP 服務器用於服務網頁請求,同時會幫助啓動 Webpack ,並接收 Webpack 發出的文件更變信號,通過 WebSocket 協議自動刷新網頁做到實時預覽。

好了,我們實踐一下,安裝 webpack-dev-server 這裏有版本兼容問題,我用的是2.9.4,[email protected],大家需要注意以下。

npm i -D webpack-dev-server

運行命令 webpack-dev-serve , 如下運行成功,此時有一個地方,注意看,第三行,四行
在這裏插入圖片描述
這意味着 DevServer 啓動的 HTTP 服務器監聽在 http://localhost:8081/ ,DevServer 啓動後會一直駐留在後臺保持運行。

細心的小夥伴已經發現了問題,我們的打開 http://localhost:8081/ 發現網頁內容沒錯,可是樣式卻沒了,而且 ./dist/bundle.js加載404了;原因是 DevServer 會把 Webpack 構建出的文件保存在內存中,在要訪問輸出的文件時,必須通過HTTP服務訪問。 由於DevServer不會理會 webpack.config.js 裏配置的output.path屬性,所以正確的 index.html 應該修改爲:

<link rel="stylesheet" href="main_69bba57c.css">
<script src="bundle.js"></script>

然後大家再嘗試着修改任何文件,會發現,猶如熱更新一樣,隨着修改,終端和網頁都在隨之刷新。
好了,第一章節就到這了,我們下章見。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章