1. 程式人生 > >ES6模組化及webpack配置

ES6模組化及webpack配置

webpack安裝

  1. 安裝 node & npm(因為webpack是基於node開發的)
  2. 通過 npm / yarn 的方式來安裝 webpack
    安裝方式:
    • 全域性安裝
      • npm install -g webpack
      • -g : global 全域性
        • 會裝在npm預設目錄
        • 好處:只需要安裝一次,本機中任何專案都可以直接使用
        • 缺點:如果本機專案中所依賴的webpack版本不一致會有一些問題。
        • 官方推薦安裝 本地(根據當前專案來安裝)
    • 本地安裝
      • npm install –save-dev webpack
      • 可在node_modules 目錄中查詢;
      • 不同專案可使用不同版本。

模組化

  • 把具有一定獨立功能的程式碼放到一個單獨的檔案中,每一個檔案就是一個模組。
  • 優勢:管理方便、易於複用
  • 解決:專案開發過程中的衝突、依賴

node出現以後,node必須有模組化,node實現了一個簡易的模組框架,並流行起來,同時為其定義一些標準:
CommonJS規範
CommonJS規範是適合使用在服務端的,是同步載入,客戶端(瀏覽器)並不適合使用,所以後來有人就參考CommonJS規範定義一些適用於web的模組化規範:

  • 1.AMD(Asynchronous Module Definition),前置依賴。
    • 適用於瀏覽器。
    • 基於AMD的requireJS模組化庫
  • 2.CMD(Common Module Definition),CMD則是依賴就近。
    • 適用於伺服器
    • 基於CMD的seaJS模組化庫

注意:自從出來後ES6,AMD及CMD基本不用了,而是用ES6中自帶的模組化。

ES6模組化

  • 基本規則
    • 1:每一個模組只加載一次, 每一個JS只執行一次, 如果下次再去載入同目錄下同檔案,直接從記憶體中讀取。 一個模組就是一個單例,或者說就是一個物件;
    • 2:每一個模組內宣告的變數都是區域性變數,不會汙染全域性作用域;
    • 3:模組內部的變數或者函式可以通過export匯出;
    • 4:一個模組可以匯入別的模組

說明:
1. export var a=100,那麼對應的寫法可以用*號的方式去匯入,如import * as m1 from './2';

;“as m1”意思是取一個別名叫做“m1”,或者import {a} from './2';
2. 用*號的匯入方式,對應的匯出方式可以是任意的。它得到的是一個Object物件
- 1.js:import * as m1 from './2';,“./2”實際是“./2.js”,可不寫字尾。
- 2.js:export var a=120;

3. 舉例:
- 1.js:

        <code>
            / 匯出一組資料
            var a = 100;
            var b = 200;
            var c = function() {};
            export {a, b, c}
        </code>
- 2.js: ``` import {a, b, c} from './2';```</br>
也就是說如果要用{}的形式匯入,那麼接收的時候就需要注意:匯出的名字和接收的名字是對應的,類似解構賦值。

Babel是一個javascript編譯器,也是用node寫的,可以將ES6+轉換成Es5,但並不解析程式碼中的 import 或 require 指令。因此,我們需要一個打包工具,可用webpack。

webpack配置

webpack可以將AMD、CMD及ES6模組化程式碼編譯成CommonJS。

  • 1.圖示:

  • 2.核心概念

    • 1.入口(entry)
      • entry:指定我們的專案打包檔案的入口檔案
      • entry可以接收:[string, array, object]三種類型。
      • 如果我們的應用程式只有一個入口的時候,可以直接使用字串形式
      • 如果我們的程式有多個入口,那麼可以使用陣列或者物件形式
      • 單檔案:一個入口
      • 單檔案多入口:陣列:index.html 載入了兩個或多個js
      • 多檔案多入口:物件
        //entry: ‘./src/1.js’,
    • 2.輸出(output):指定打包後的檔案生成配置

      • 1.打包後的檔案存放的目錄: 
         path: path.resolve(__dirname, “dist”),
        • __dirname : 常量,返回當前檔案所在的絕對路徑
        • path.resolve:返回(處理)不同作業系統的絕對路徑問題
      • 2.生成後的檔名:

        • (1)對於單個入口起點,filename 會是一個靜態名稱。filename: ‘bundle.js’;
        • (2)當通過多個入口起點(entry point)、程式碼拆分(code splitting)或各種外掛(plugin)建立多個 bundle,應該使用以下一種替換方式,來賦予每個 bundle 一個唯一的名稱:

          • a.入口名稱: filename: “[name].bundle.js”;
          • 、、、、、、
          • d.使用基於每個 chunk 內容的 hash:filename: “[chunkhash].bundle.js”
            注意:使用hash值做檔名,是為了使每次打包生成的檔案的檔名不一樣,解決JS快取問題。

            <code>
                const webpack=require("webpack");
                const path=require("path");
                module.exports={
                    entry:{
                        a:"./src/1.js"
                    },
                    output:{
                        path:path.resolve(__dirname,"dist"),
                        filename:'bundle.js'
                    }
                };
            </code>
            
    • 3.loader

      • (1) 檔案打包前處理器,webpack首先會去載入指定檔案(css、js、html、txt、png等)各種資原始檔,然後進行打包,但是webpack本身只能處理js,像css被打包後可能就會執行出錯,Loader就派上用場了,Loader其實就是打包前處理器。
        預處理:預先處理,webpack會呼叫各種Loader對非js的資源進行預先處理,處理完成(處理成js能夠識別的資料)以後交給webpack進行打包。

      • (2) 在使用loader之前需要安裝指定的loader:npm install loader。

      • (3)loader 也能夠使用 options 物件進行配置。
      • (4)在 webpack.config.js 檔案中進行配置:
        rules:配置Loader載入和處理規則;

        • test: /\.txt$/
          被載入的資原始檔的字尾,
        • use: ‘raw-loader’;
          當載入的資源滿足test的時候,呼叫use指定的loader去該資源進行解析處理。

          <code>
              {
                  ...,
                  //配置第三方模組,比如Loader就在這裡配置
                  module: {
                      rules: [
                          //每一個規則是一個物件
                          {
                              test: /\.txt$/,
                              use: 'raw-loader'
                          }
                      ]
                  }
              }
          </code>
          
      • (4)常用的loader

        • (1)raw-loader:處理源資料;
        • (2)file-loader: 解析並返回檔案的路徑;

          <code>
              {
               test: /\.png$/,
               //use: 'file-loader'
               use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name].[ext]'
                        }
                    }
                ]
              }
          </code>
          
        • (3)url-loader:像 file loader 一樣工作,但如果檔案小於限制,可以返回 data URL

          <code>
              {
                  test: /\.(png|jpg|gif)$/,
                  use: [
                    {
                        loader: 'url-loader',
                        options: {
                            // 設定小於limit值生成dataURL,否則生成url
                            limit: 819200
                        }
                    }
                  ]
              }
          </code>
          
        • (4)css-loader:解析 CSS 檔案後,使用 import 載入,並且返回CSS程式碼;
        • (5)style-loader:將模組的匯出作為樣式新增到DOM中;

          <code>
              {
                test: /\.css$/,
                use: [
                   // 從下向上執行,所以別寫反了!!!
                    'style-loader',
                    'css-loader'
                ]
              }
          </code>
          
        • (5)json-loader
          注意:webpack >= v2.0.0 預設支援匯入 JSON 檔案,不需再下載json的loader。
    • 4.外掛(plugins)
      和Loader類似,但是他是打包後執行,對打包後的檔案做進一步的處理。

      • 壓縮外掛:webpack.optimize.UglifyJsPlugin是webpack的核心外掛,是自帶的,直接使用。
        UglifyJsPlugin與webpack.optimize.UglifyJsPlugin功能相同,但是需要安裝外掛才能用。
      • ExtractTextWebpackPlugin:從 bundle 中提取文字(CSS)到單獨的檔案。
        如下文程式碼所示,它會將所有的入口 chunk(entry chunks)中引用的 *.css,移動到獨立分離的 CSS 檔案。因此,你的樣式將不再內嵌到 JS bundle 中,而是會放到一個單獨的 CSS 檔案(即 styles.css)當中。 如果你的樣式檔案大小較大,這會做更快提前載入,因為 CSS bundle 會跟 JS bundle 並行載入。
  • 2.配置:webpack.config.js

    <code>
        const path = require('path');
        const webpack = require('webpack');
        const ExtractTextPlugin = require("extract-text-webpack-plugin");
    
        module.exports = {
            entry: {
                 UglifyJSPlugin: './src/UglifyJSPlugin.js'
            },
            output: {
    
                path: path.resolve(__dirname, "dist"),
                filename: '[name].bundle.js',
                //filename: '[chunkhash].bundle.js'
    
                // 設定打包後的資源的載入
                publicPath: "./dist/"
            },
            module: {
                rules: [
                    {
                        test: /\.css$/,
                        use: ExtractTextPlugin.extract({
                            fallback: "style-loader",
                            use: "css-loader"
                        })
                    }
                ]
            },
            // 外掛配置
            plugins: [
                new webpack.optimize.UglifyJsPlugin(),
                new ExtractTextPlugin("styles.css")
            ]
        };
    </code>
    

本地webpack執行

  • 方法一:

    • 1.在 package.json 新增一個 npm 指令碼(npm script);

      <code>      
          {
            ...
            "scripts": {
              "build": "webpack -w"
            },
            ...
          }
      </code>
      
    • 2.執行“npm run build”命令,可得到如下圖所示:
  • 方法二:
    在當前目錄下,執行“.\node_modules.bin\webpack -w”命令。

注意:”webpack -w”中的“-w”命令是監聽相關檔案是否被修改,若修改則自動重新執行webpack,不用再自己手動重啟。

全域性webpack執行

在當前目錄下,執行“webpack -w”命令。

模組熱替換

模組熱替換,Hot Module ReplaceMent(HMR)。

  • 可以在應用程式執行過程中替換、新增或刪除模組,而無需重新載入整個頁面。效果上就是介面的無重新整理更新。
  • 這個功能主要是用於開發過程中,對生產環境沒有什麼幫助。
  • 過程:
    • (1)首先需要安裝Webpack-dev-server,一個輕量的node.js express伺服器。
      “npm install webpack-dev-server –save-dev”
      注意:Webpack-dev-server十分小巧,這裡的作用是用來伺服資原始檔,不能替代後端的伺服器。

複製本目錄下的 package.json 和 webpack.config.js 檔案
// package.json

<code>
    {
      "name": "003",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "webpack-dev-server --env development",
        "dev": "webpack-dev-server --env development",
        "build": "webpack --env production"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "html-webpack-plugin": "^2.28.0",
        "webpack": "^2.3.2",
        "webpack-dev-server": "^2.4.2"
      }
    }
</code>

// webpack.config.js

<code>
    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');

    module.exports = {
      devServer: {
        host: process.env.HOST, // Defaults to `localhost`
        port: 8080, // Defaults to 8080
      },
      entry: {
        app: "./app/app.js",
      },
      output: {
        path: path.resolve(__dirname,"build"),
        filename: '[name].js',
      },
      plugins: [
        new HtmlWebpackPlugin({
          title: 'hot replace',
        }),
      ],
    };
</code>

npm i

npm run dev 或者 npm run start 這些可以在 package.json 中配置

瀏覽器開啟 localhost:8080 埠號可以在webpack.config.js 中配置

熱模組打包的資源是存在於記憶體中的
使用熱模組能為我們的開發帶來很多便利