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

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

#### 模組化規範 ##### 傳統開發模式主要問題 ```go /* 1. 命名衝突 2. 檔案依賴 */ ``` `通過模組化解決上述問題` ```go /* 模組化就是把單獨的一個功能封裝在一個模組(檔案)中,模組之間相互隔離, 但是可以通過特定的介面公開內部成員,也可以依賴別的模組. 模組化開發好處: 方便程式碼的重用,從而提高開發效率,並且方便後期的維護 */ ``` ##### 瀏覽器模組化規範 ```go /* AMX (Require.js) CMD (Sea.js) */ ``` ##### 伺服器端模組化規範 ```go /* CommonJS 1.模組分文單檔案模組與包 2.模組成員匯出: module.exports和exports 3.模組成員匯入: require('模組識別符號') */ ``` #### ES6模組化 > 在ES6模組化規範之前,Javascript社群已經嘗試並提出了AMD,CMD,CommonJS等模組化規範. > > 但是,這些社群提出的模組化標準還是存在一定的差異性與侷限性,並不是瀏覽器與伺服器通用的模組化標準,例如: ```go /* AMD和CMD適用於瀏覽器端的JavaScript模組化 CommonnJS適用於伺服器端的JavaScript模組化 */ ``` > 因此,在ES6語法規範中,在語言層面上定義了ES6模組化規範,是瀏覽器與伺服器端通用的模組化開發規範. `ES6模組化規範中定義` ```go /* 1. 每個js檔案都是一個獨立的模組 2. 匯入模組成員使用import關鍵字 3. 暴露模組成員使用export關鍵字 */ ``` `推薦使用ES6模組化,因為AMD,CMD侷限使用與瀏覽器端,而CommonJS在伺服器端使用。 ES6模組化是瀏覽器端和伺服器端通用的規範.` ##### Node.js通過babel體驗ES6模組化 `1.安裝babel` ```node 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檔案中的程式碼如下` ```vue const presets = [ ["@babel/env",{ targets:{ edge:"17", firefox:"60", chrome:"67", safari:"11.1" } }] ] //暴露 module.exports = { presets } ``` `3.建立index.js檔案` ```go /* 在專案目錄中建立index.js檔案作為入口檔案 在index.js中輸入需要執行的js程式碼,例如: console.log("ok"); */ ``` `4.使用npx執行檔案` ` 開啟終端,輸入命令:npx babel-node ./index.js` ##### 預設匯出 > 預設匯出語法為export default 預設匯出的成員 ```vue export default { 成員A, 成員B, ....... },如下: let num = 100; export default{ num } ``` `Example1` ```vue // 當前檔案模組為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 '模組識別符號' ```vue // 匯入模組成員 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 ```vue export let num = 998; export let myName = "jack"; export function fn = function(){ console.log("fn") } ``` `Example` ```vue // 當前檔案模組為m1.js // 向外按需匯出變數為s1 export let s1 = 'aaa' // 向外按需匯出變數為s2 export let s2 = 'ccc' // 向外按需匯出方法 say export function say = function() {} ``` ##### 按需匯入 > 按需匯入語法 > > Import { s1 } from '模組識別符號' ```go import { num,fn as printFn ,myName } from "./test.js" // 同時匯入預設匯出的成員以及按需匯入的成員 import test,{ num,fn as printFn ,myName } from "./test.js" // 注意:一個模組中既可以按需匯入也可以預設匯入,一個模組中既可以按需匯出也可以預設匯出 ``` `Example1` ```vue // 匯入模組成員 import { s1,s2 as ss2, say } from './m1.js' console.log(s1) // 列印輸出aaa console.log(s2) // 列印輸出ccc console.log(say) // 列印輸出[Function: say] ``` `直接匯入並執行程式碼` > 有時候,我們`只想單純執行某個模組的程式碼,並不需要得到模組中向外暴露的成員`,此時,可以直接匯入並執行模組程式碼 ```vue import "./test2.js"; ``` `m1.js` ```vue // 當前檔案模組為m2.js // 在當前模組中執行一個for迴圈操作 for(let i=0;i<3;i++){ console.log(i) } ``` #### Webpack概念 ##### 當前Web開發面臨的困境 ```go /* 檔案依賴關係錯綜複雜 靜態資源請求效率低 模組化支援不友好 瀏覽器對高階JavaScript特性相容程度較低 */ ``` >
webpack是一個流行的前端專案構建工具,可以解決目前web開發的困境。 > webpack提供了模組化支援,程式碼壓縮混淆,解決js相容問題,效能優化等特性,提高了開發效率和專案的可維護性 ![](https://img2020.cnblogs.com/blog/1871335/202011/1871335-20201120144829266-1263163619.png) #### WebPack的基本使用 ```go /* 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 ```go /* 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的打包入口/出口 ```go /* 在webpack 4.x中. 預設會將src/index.js 作為預設的打包入口js檔案 預設會將dist/main.js 作為預設的打包輸出js檔案 */ ``` >
如果不想使用預設的入口/出口js檔案,我們可以通過改變 webpack.config.js 來設定入口/出口的js檔案,如下: ```vue 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的自動打包 ```go /* 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地址,檢視自動打包效果 */ ``` `注意` ```go /* 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/的時候,看到的是一些檔案和資料夾,想要檢視我們的頁面 > 還需要點選資料夾點選檔案才能檢視,那麼我們希望預設就能看到一個頁面,而不是看到資料夾或者目錄。 > 實現預設預覽頁面功能的步驟如下: ```go 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載入器包含` ```go /* 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呼叫過程 ![](https://img2020.cnblogs.com/blog/1871335/202011/1871335-20201120164512380-1345353585.png) ##### webpack中載入器的基本使用 **打包處理css檔案** ```go /* 執行npm i style-loader css-loader -D 命令, 安裝處理的css檔案的loader */ ``` `2. 在webpack.config.js的module --> rules 陣列中,新增loader規則如下` ```go // 所有第三方檔案模組的匹配規則 module: { rules: [ { test: /\.css$/,use: ['style-loader','css-loader'] } ] } // 其中, test表示匹配的檔案型別, use表示對應要呼叫的loader ``` `注意` ```go /* use陣列中指定的loader順序是固定的. 多個loader的呼叫順序是: 從後往前呼叫 */ ``` **處理less檔案** ```go 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檔案 ```go 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的相容字首 ```go 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'] } ] } } ``` ##### 打包樣式表中的圖片以及字型檔案 ```go // 在樣式表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高階語法 ```go /* 在編寫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)` ##### 解決方案 ```go /* 使用Vue單檔案元件,每個單檔案元件的字尾名都是.vue 每一個Vue單檔案元件都由三部分組成 1).template 元件組成的模板區域 2).script 組成的業務邏輯區域 3).style 樣式區域 */ ``` `Example` ```vue ``` `安裝Vetur外掛可以使得.vue檔案中的程式碼高亮` ##### 配置.vue檔案的載入器 ```go // 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單檔案元件。` ```go /* 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打包釋出專案 `在專案上線之前,我們需要將整個專案打包併發布` ```go /* A.配置package.json "scripts":{ "dev":"webpack-dev-server", "build":"webpack -p" } B.在專案打包之前,可以將dist目錄刪除,生成全新的dist目錄