07 . 前端工程化(ES6模組化和webpack打包css,less,scss,圖片,字型,配置Vue元件載入器和釋出專案)

youmen發表於2020-11-20

模組化規範

傳統開發模式主要問題
/*
		1. 命名衝突
		2. 檔案依賴
*/

通過模組化解決上述問題

/*
		模組化就是把單獨的一個功能封裝在一個模組(檔案)中,模組之間相互隔離,
			但是可以通過特定的介面公開內部成員,也可以依賴別的模組.
		
		模組化開發好處:
				方便程式碼的重用,從而提高開發效率,並且方便後期的維護
*/
瀏覽器模組化規範
/*
		AMX   (Require.js)
		CMD		(Sea.js)
*/
伺服器端模組化規範
/*
		CommonJS
				1.模組分文單檔案模組與包
				2.模組成員匯出: module.exports和exports
				3.模組成員匯入: require('模組識別符號')
*/

ES6模組化

在ES6模組化規範之前,Javascript社群已經嘗試並提出了AMD,CMD,CommonJS等模組化規範.

但是,這些社群提出的模組化標準還是存在一定的差異性與侷限性,並不是瀏覽器與伺服器通用的模組化標準,例如:

/*
		AMD和CMD適用於瀏覽器端的JavaScript模組化
		CommonnJS適用於伺服器端的JavaScript模組化
*/

因此,在ES6語法規範中,在語言層面上定義了ES6模組化規範,是瀏覽器與伺服器端通用的模組化開發規範.

ES6模組化規範中定義

/*
		1. 每個js檔案都是一個獨立的模組
		2. 匯入模組成員使用import關鍵字
		3. 暴露模組成員使用export關鍵字
*/

推薦使用ES6模組化,因為AMD,CMD侷限使用與瀏覽器端,而CommonJS在伺服器端使用。 ES6模組化是瀏覽器端和伺服器端通用的規範.

Node.js通過babel體驗ES6模組化

1.安裝babel

npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/node
npm install --save @babel/polyfill

2.建立babel.config.js

在專案目錄中建立babel.config.js檔案。
編輯js檔案中的程式碼如下

        const presets = [
            ["@babel/env",{
                targets:{
                    edge:"17",
                    firefox:"60",
                    chrome:"67",
                    safari:"11.1"
                }
            }]
        ]
        //暴露
        module.exports = { presets }

3.建立index.js檔案

/*
		在專案目錄中建立index.js檔案作為入口檔案
    在index.js中輸入需要執行的js程式碼,例如:
        console.log("ok");
*/

4.使用npx執行檔案

開啟終端,輸入命令:npx babel-node ./index.js

預設匯出

預設匯出語法為export default 預設匯出的成員

    export default {
        成員A,
        成員B,
        .......
    },如下:
    let num = 100;
    export default{
        num
    }

Example1

// 當前檔案模組為m1.js

// 定義私有成員a和c
let a = 10
let c = 20
let d = 30

// 外界訪問不到變數b,因為他沒有被暴露出去
function show() {
    console.log('1111')
}


// 將本模組的私有成員暴露出去,供其他模組使用
export default {
    a,
    c,
    show
}
預設匯入

預設匯入語法import 接受名稱 from '模組識別符號'

// 匯入模組成員
import m1 from './m1/m1.js'

console.log(m1)

// 列印輸出的結果為:
youmen@bogon Vue_Student_Demo % npx babel-node ./index.js
{ a: 10, c: 20, d: 30, show: [Function: show] }

注意: 每個模組中,只允許使用唯一的一次export default,否則會報錯

按需匯出

按需匯出語法

Export let s1 = 10

    export let num = 998;
    export let myName = "jack";
    export function fn = function(){ console.log("fn") }

Example

// 當前檔案模組為m1.js

// 向外按需匯出變數為s1
export let s1 = 'aaa'

// 向外按需匯出變數為s2
export let s2 = 'ccc'

// 向外按需匯出方法 say
export function say = function() {}
按需匯入

按需匯入語法

Import { s1 } from '模組識別符號'

    import { num,fn as printFn ,myName } from "./test.js"
    // 同時匯入預設匯出的成員以及按需匯入的成員
    import test,{ num,fn as printFn ,myName } from "./test.js"
// 注意:一個模組中既可以按需匯入也可以預設匯入,一個模組中既可以按需匯出也可以預設匯出

Example1

// 匯入模組成員
import {  s1,s2 as ss2, say } from './m1.js'

console.log(s1)  // 列印輸出aaa
console.log(s2)  // 列印輸出ccc
console.log(say) // 列印輸出[Function: say]

直接匯入並執行程式碼

有時候,我們只想單純執行某個模組的程式碼,並不需要得到模組中向外暴露的成員,此時,可以直接匯入並執行模組程式碼

import "./test2.js";

m1.js

// 當前檔案模組為m2.js

// 在當前模組中執行一個for迴圈操作
for(let i=0;i<3;i++){
	console.log(i)
}

Webpack概念

當前Web開發面臨的困境
/*
		檔案依賴關係錯綜複雜
		靜態資源請求效率低
		模組化支援不友好
		瀏覽器對高階JavaScript特性相容程度較低
*/

webpack是一個流行的前端專案構建工具,可以解決目前web開發的困境。
webpack提供了模組化支援,程式碼壓縮混淆,解決js相容問題,效能優化等特性,提高了開發效率和專案的可維護性

WebPack的基本使用

/*
	1.建立列表隔行變色專案
     新建專案空白目錄,並執行npm init -y 命令, 初始化包管理配置檔案package.json

  2.新建src原始碼目錄

  3.新建src/index.html首頁
  
  4. 初始化首頁基本結構
  
  5. 執行 npm install jquery -s 命令,安裝jQuery
  		匯入jQuery
        開啟index.js檔案,編寫程式碼匯入jQuery並實現功能:
        import $ from "jquery";
        $(function(){
            $("li:odd").css("background","cyan");
            $("li:odd").css("background","pink");
        })
  
  6. 通過模組化形式,實現列表隔行變色效果
*/

注意:此時專案執行會有錯誤,因為import $ from "jquery";這句程式碼屬於ES6的新語法程式碼,在瀏覽器中可能會存在相容性問題 所以我們需要webpack來幫助我們解決這個問題。

專案中配置webpack
/*	
		1).開啟專案目錄終端,輸入命令:
        npm install webpack webpack-cli -D
    
    2).然後在專案根目錄中,建立一個 webpack.config.js 的配置檔案用來配置webpack
        在 webpack.config.js 檔案中編寫程式碼進行webpack配置,如下:
        module.exports = {
            mode:"development"//可以設定為development(開發模式),production(釋出模式)
        }
        補充:mode設定的是專案的編譯模式。
        如果設定為development則表示專案處於開發階段,不會進行壓縮和混淆,打包速度會快一些

        如果設定為production則表示專案處於上線釋出階段,會進行壓縮和混淆,打包速度會慢一些
   
    3).修改專案中的package.json檔案新增執行指令碼dev,如下:
        "scripts":{
            "dev":"webpack"
        }
        注意:scripts節點下的指令碼,可以通過 npm run 執行,如:
        執行終端命令:npm run dev
        將會啟動webpack進行專案打包
    
    4).執行dev命令進行專案打包,並在頁面中引入專案打包生成的js檔案
        開啟專案目錄終端,輸入命令:
        npm run dev
        等待webpack打包完畢之後,找到預設的dist路徑中生成的main.js檔案,將其引入到html頁面中。
        瀏覽頁面檢視效果。
*/	
設定Webpack的打包入口/出口
/*
		  在webpack 4.x中.
          預設會將src/index.js 作為預設的打包入口js檔案
          預設會將dist/main.js 作為預設的打包輸出js檔案
*/

如果不想使用預設的入口/出口js檔案,我們可以通過改變 webpack.config.js 來設定入口/出口的js檔案,如下:

    const path = require("path");  // 匯入node.js中專門操作路徑的模組
    module.exports = {
        mode:"development",
        // 設定入口檔案路徑
        entry: path.join(__dirname,"./src/xx.js"),

        //設定出口檔案
        output:{
            //設定輸出檔案路徑
            path:path.join(__dirname,"./dist"),
            //設定輸出檔名稱
            filename:"res.js"
        }
    }
Webpack的自動打包
/*
		1. 執行npm install webpack-dev-server -D 命令,安裝支援專案自動打包的工具
		
		2. 修改package.json  --> scripts中的dev命令如下
				"scripts": {
						"dev": "webpack-dev-server"  // script節點下的指令碼,可以通過npm run執行
				}
				
		3. 將src --> index.html中,script指令碼的引用路徑,修改為 "/buldle.js"
		
		4. 執行npm run dev命令, 重新進行打包
		
		5. 瀏覽器中訪問http://localhost:8080地址,檢視自動打包效果
*/

注意

/*
		webpack-dev-server   會啟動一個實時打包的http伺服器
		webpack-dev-server	 打包生成的輸出檔案,預設放到了專案根目錄中,而且是虛擬機器的,看不見的
		在自動打包完畢之後,預設開啟伺服器網頁,實現方式就是開啟package.json檔案,修改dev命令:
    "dev": "webpack-dev-server --open --host 127.0.0.1 --port 9999"
*/
配置預設預覽頁面

使用html-webpack-plugin 可以生成一個預覽頁面。
因為當我們訪問預設的 http://localhost:8080/的時候,看到的是一些檔案和資料夾,想要檢視我們的頁面
還需要點選資料夾點選檔案才能檢視,那麼我們希望預設就能看到一個頁面,而不是看到資料夾或者目錄。
實現預設預覽頁面功能的步驟如下:

      A.安裝預設預覽功能的包:html-webpack-plugin
          npm install html-webpack-plugin -D
      B.修改webpack.config.js檔案,如下:
          //匯入包
          const HtmlWebpackPlugin = require("html-webpack-plugin");
          //建立物件
          const htmlPlugin = new HtmlWebpackPlugin({
              //設定生成預覽頁面的模板檔案
              template:"./src/index.html",
              //設定生成的預覽頁面名稱,該檔案存在於記憶體中,在目錄中不顯示
              filename:"index.html"
          })
      C.繼續修改webpack.config.js檔案中向外暴露的配置物件,新增plugins資訊:
          module.exports = {
              ......
              plugins:[ htmlPlugin ]
    						// plugins陣列是webpack打包期間會用到的一些外掛列表
          }

Webpack中的載入器

通過loader打包非js模組

通過loader打包非js模組:預設情況下,webpack只能打包js字尾名結尾的檔案,如果想要打包非js檔案,需要呼叫loader載入器才能打包.

Loader載入器包含

/*
    1).less-loader:  處理.less相關檔案
    2).sass-loader:  處理.scss相關檔案
    3).url-loader:  打包處理css中與url路徑有關的檔案
    4).babel-loader:處理高階js語法的載入器
    5).postcss-loader
    6).css-loader,style-loader
*/
loader呼叫過程

webpack中載入器的基本使用

打包處理css檔案

/*
		執行npm i style-loader css-loader -D 命令, 安裝處理的css檔案的loader
*/

2. 在webpack.config.js的module --> rules 陣列中,新增loader規則如下

//  所有第三方檔案模組的匹配規則
	module: {
		rules: [
			{ test: /\.css$/,use: ['style-loader','css-loader'] }
		]
	}

// 其中, test表示匹配的檔案型別, use表示對應要呼叫的loader

注意

/*
		use陣列中指定的loader順序是固定的.
		多個loader的呼叫順序是: 從後往前呼叫
*/

處理less檔案

1).安裝包
    npm install less-loader less -D
2).配置規則:更改webpack.config.js的module中的rules陣列
module.exports = {
	// 編譯模式
	mode: 'development', // development  production
	entry: path.join(__dirname, './src/index.js'),
	output: {
		path: path.join(__dirname, './dist'), // 輸出檔案的存放路徑
		filename: 'bundle.js' // 輸出檔案的名稱
	},
	plugins: [htmlPlguin],
	module: {
		rules: [
			{ test: /\.css$/,use: ['style-loader','css-loader'] },
			{ test: /\.less$/,use: ['style-loader','css-loader','less-loader' ]}
		]
	}
}
打包處理scss檔案
npm i sass-loader node-sass -D

// 在webpack.connfig.js的module->rules陣列中,新增loader規則如下
module: {
  rules: {
    { test: /\.scss$/,use: ['style-loader','css-loader','sass-loader'] }
  }
}
配置postcss自動新增css的相容字首
1).安裝包
    npm install postcss-loader autoprefixer -D
2).在專案根目錄建立並配置postcss.config.js檔案
const autoprefixer = require("autoprefixer");
module.exports = {
    plugins:[ autoprefixer ]
}
3).配置規則:更改webpack.config.js的module中的rules陣列
module.exports = {
    ......
    plugins:[ htmlPlugin ],
    module : {
        rules:[
            {
                //test設定需要匹配的檔案型別,支援正則
                test:/\.css$/,
                //use表示該檔案型別需要呼叫的loader
                use:['style-loader','css-loader','postcss-loader']
            },
            {
                test:/\.less$/,
                use:['style-loader','css-loader','less-loader']
            },
            {
                test:/\.scss$/,
                use:['style-loader','css-loader','sass-loader']
            }
        ]
    }
}
打包樣式表中的圖片以及字型檔案
// 在樣式表css中有時候會設定背景圖片和設定字型檔案,一樣需要loader進行處理
// 使用url-loader和file-loader來處理打包圖片檔案以及字型檔案
1).安裝包
    npm install url-loader file-loader -D
2).配置規則:更改webpack.config.js的module中的rules陣列
module.exports = {
    ......
    plugins:[ htmlPlugin ],
    module : {
        rules:[
            {
                //test設定需要匹配的檔案型別,支援正則
                test:/\.css$/,
                //use表示該檔案型別需要呼叫的loader
                use:['style-loader','css-loader']
            },
            {
                test:/\.less$/,
                use:['style-loader','css-loader','less-loader']
            },
            {
                test:/\.scss$/,
                use:['style-loader','css-loader','sass-loader']
            },{
                test:/\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2$/,
                //limit用來設定位元組數,只有小於limit值的圖片,才會轉換
                //為base64圖片
                use:"url-loader?limit=16940"
            }
        ]
    }
}
打包js高階語法
/*
    在編寫js的時候,有時候我們會使用高版本的js語法
    有可能這些高版本的語法不被相容,我們需要將之打包為相容性的js程式碼
    我們需要安裝babel系列的包
    A.安裝babel轉換器
        npm install babel-loader @babel/core @babel/runtime -D
    B.安裝babel語法外掛包
        npm install @babel/preset-env @babel/plugin-transform-runtime @babel/plugin-proposal-class-properties -D
    C.在專案根目錄建立並配置babel.config.js檔案
*/
    
    module.exports = {
        presets:["@babel/preset-env"],
        plugins:[ "@babel/plugin-transform-runtime", "@babel/plugin-proposal-class-properties" ]
    }
//   D.配置規則:更改webpack.config.js的module中的rules陣列
module.exports = {
	// 編譯模式
	mode: 'development', // development  production
	entry: path.join(__dirname, './src/index.js'),
	output: {
		path: path.join(__dirname, './dist'), // 輸出檔案的存放路徑
		filename: 'bundle.js' // 輸出檔案的名稱
	},
	plugins: [htmlPlguin],
	module: {
		rules: [
		  { test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] },
		  { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
		  { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
		  { test: /\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2$/, use: 'url-loader?limit=16941' },
		  { test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
		]
	}
}

Vue單檔案元件

傳統Vue元件的缺陷

全域性定義的元件不能重名,字串模板缺乏語法高亮,不支援css(當html和js元件化時,css沒有參與其中) 沒有構建步驟限制,只能使用H5和ES5,不能使用前處理器(babel)

解決方案
/*
		使用Vue單檔案元件,每個單檔案元件的字尾名都是.vue
      每一個Vue單檔案元件都由三部分組成
      1).template  元件組成的模板區域
      2).script   組成的業務邏輯區域
      3).style  樣式區域
*/

Example

<template>
    元件程式碼區域
</template>

<script>
    js程式碼區域
</script>

<style scoped>
    樣式程式碼區域
</style>

安裝Vetur外掛可以使得.vue檔案中的程式碼高亮

配置.vue檔案的載入器
// A.安裝vue元件的載入器
    npm install vue-loader vue-template-compiler -D
// B.配置規則:更改webpack.config.js的module中的rules陣列
    const VueLoaderPlugin = require("vue-loader/lib/plugin");
    const vuePlugin = new VueLoaderPlugin();
    module.exports = {
        ......
        plugins:[ htmlPlugin, vuePlugin  ],
        module : {
            rules:[
                ...//其他規則
                { 
                    test:/\.vue$/,
                    loader:"vue-loader",
                }
        ]
    }
}

Webpack中使用Vue

想要讓vue單檔案元件能夠使用,我們必須要安裝vue並使用vue來引用vue單檔案元件。

/*
    A.安裝Vue
        npm install vue -S
    B.在index.js中引入vue:import Vue from "vue"
    C.建立Vue例項物件並指定el,最後使用render函式渲染單檔案元件
        const vm = new Vue({
            el:"#first",
            render:h=>h(app)
        })
*/

Webpack打包釋出專案

在專案上線之前,我們需要將整個專案打包併發布

/*
		A.配置package.json
    "scripts":{
        "dev":"webpack-dev-server",
        "build":"webpack -p"
    }
		B.在專案打包之前,可以將dist目錄刪除,生成全新的dist目錄	
*/

相關文章