07 . 前端工程化(ES6模組化和webpack打包css,less,scss,圖片,字型,配置Vue元件載入器和釋出專案)
阿新 • • 發佈:2020-11-20
#### 模組化規範
##### 傳統開發模式主要問題
```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目錄