第15章 git和webpack常用開發環境【不會這些,你就會被認定是菜鳥小白,沒做過項目】

返回章節目錄

目錄

1.關於開發環境

2.git介紹

3.關於chrome調試和抓包

4.關於電腦調試手機網頁

5.webpack-搭建環境

6.webpack-babel(ES6的東西轉換成ES5)

7.webpack-ES6-Module(ES6的模塊化)

單個導出

一起導出

8.webpack-配置生產環境


 

 

 

1.關於開發環境

面試官想通過開發環境瞭解候選人的實際工作情況,而開發環境的工具能體現工作產出的效率,這些問題會以聊天形式爲主,不會問具體的問題。

在這裏1、2、3、4點我都是隻是概述總結,沒有細講,因爲每個都是長篇大論而且網上搜得到

5、6、7、8是從0到1搭建webpack環境並且運行,如果有一點webpack經歷,這應該是一個很好的複習

 

2.git介紹

關於git,不講命令,由於篇幅太大,我另外寫了一篇,方便跳轉過去看,鏈接如下

Git從開發到上線中那些事和個人體會

 

3.關於chrome調試和抓包

面試不考,卻是程序員寫代碼的必備技能,講起來是一個非常長的篇幅,網上能搜到很多

關於chrome調試,自己搜一下進行學習

關於抓包

移動端的h5頁面查看網絡請求的時候,需要用工具抓包

windows一般用fiddler,Mac OS一般用charles,我個人是用的charles

問題來了,怎麼學習呢?搜索“fiddler如何使用”之類的,或者“charles如何使用”之類的。

當usb連接之後,開始準備抓包的時候,有強校驗的app是無法運行的,會報網絡環境異常之類的錯誤

4.關於電腦調試手機網頁

面試不考,仍然是內功技能。講起來是一個非常長的篇幅,網上能搜到很多

如果利用chrome瀏覽器,需要翻牆,可以搜索"chrome手機調試",調試的時候可以看到網頁源代碼和手機頁面,總體來講我個人認爲需要翻牆體驗不太好也太麻煩,萬一公司不讓翻牆呢?需要申請權限之類的呢?

如果利用firefox瀏覽器,不需要翻牆,可以搜索"firefox手機調試",但是調試的時候只看得到網頁源代碼,無法看到手機頁面,所以只能從選中代碼去選中界面中的元素,而無法直接在響應式設計界面中點擊跳轉到對應代碼。

這裏和大家說一下,避免浪費時間去踩坑,我是浪費時間去踩坑了的。

 

5.webpack-搭建環境

接下來就是簡單的demo從0--1的過程了。

先自己創建一個工程目錄,比如webpack-demo,然後進去到webpack-demo目錄

查看是否安裝node

node -v

有版本號就是安裝好了

接下來npm init -y

就自動創建了package.json ,當然也可以去掉-y,會出現下面提示,一路回車就可以,達到和-y一樣的效果

執行完之後webpack-demo目錄中多了一個package.json文件

接着執行命令npm install webpack webpack-cli -D

這個可能會出錯,可以加上淘寶鏡像去代理,這和cnpm安裝一樣的效果,淘寶鏡像目錄https://npm.taobao.org/,則運行

npm install webpack webpack-cli -D --registry=https://registry.npm.taobao.org

但是仍然有可能報錯,不知道大家是不是和我一樣執行的時候會如下報錯

No receipt for 'com.apple.pkg.CLTools_Executables' found at '/'.

No receipt for 'com.apple.pkg.DeveloperToolsCLILeo' found at '/'.

No receipt for 'com.apple.pkg.DeveloperToolsCLI' found at '/'.

gyp: No Xcode or CLT version detected!
gyp ERR! configure error
gyp ERR! stack Error: `gyp` failed with exit code: 1

我就下載安裝了一個XCode就好了,可以參見這裏的報錯經歷

接着用vscode打開目錄如下

在這裏目webpack-demo目錄下創建src目錄

接着在src裏面新建index.js

console.log("this is index js")

然後在webpack-demo目錄新建webpack.config.js,這就是webpack默認的配置文件的名字

在webpack.config.js內容如下:

const path = require('path')
module.exports = {
    mode: 'development', // production
    entry: path.join(__dirname, 'src', 'index.js'),//__dirname就是當前目錄(同一套代碼不同環境可能當前環境路徑字符串不一樣,__dirname能統一表示)
    //拼接src再拼接index.js,就能找到整個文件的入口
    output: {
        filename: 'bundle.js',
        path: path.join(__dirname, 'dist')
    }
}

接着準備運行了,我們來到package.json,在scripts裏面加上"build": "webpack",如下:

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack" 
    /*"webpack --config webpack.config.js"如果webpack配置文件名字改了,那麼就在這裏指定修改*/
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.41.5",
    "webpack-cli": "^3.3.10"
  }
}

webpack打包的時候默認配置文件是webpack.config.js,所以不用指定webpack --config webpack.config.js,除非配置文件是其它名字

接着我們執行命令,npm run build,我們指定了build爲webpack,所以等同於你執行npm run webpack

只要我們運行的是npm腳本(就是scripts裏面的),打包的時候就會顯示你的當前目錄和你的腳本命令,這裏是webpack,說明你的"build"對應"webpack",只要打包的內容不變,Hash值就不會變。Version顯示你的webpack版本,Time是你的打包花費的時間。Built at是你的打包日期。Asset地下顯示的bundle.js是生成的打包文件名,3.8KB,Chunks是js文件對應的id,Chunks Names代表每一個js對應的名字,這裏爲什麼是main,是因爲你的配置文件webpack.config.js裏的

entry: path.join(__dirname, 'src', 'index.js')其實是一種簡寫,默認如下

entry: { main: path.join(__dirname, 'src', 'index.js')},你可以把這個的main換成main2試試,如果你的Chunks就變成main2,則顯示Entrypoint main2 = bundle.js

[./src/index.js] 31 byte {main2} [built]表示打包需要的js文件

這裏麪包含了index.js的內容

webpack打包的時候要考慮自己的打包方案,所以上面的內容看到各種modulexxx

webpack可以兼容模塊化的方案,所以會加上很多模塊化的代碼

在src下面新建index.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>webpack演示</title>
    </head>
    <body>
        <p>webpack demo</p>
        <script></script>
    </body>
</html>

接着還得安裝一個解析html的插件html-webpack-plugin

npm install html-webpack-plugin -D --registry=https://registry.npm.taobao.org

繼續安裝一個能啓動服務的插件webpack-dev-server

npm install webpack-dev-server -D --registry=https://registry.npm.taobao.org

接下來要去webpack.config.js去加上插件和開啓本地服務的配置

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin') // 引進解析html的插件
module.exports = {
    mode: 'development', // production
    entry: path.join(__dirname, 'src', 'index.js'),//__dirname就是當前目錄(同一套代碼不同環境可能當前環境路徑字符串不一樣,__dirname能統一表示)
    //拼接src再拼接index.js,就能找到整個文件的入口
    output: {
        filename: 'bundle.js',
        path: path.join(__dirname, 'dist')
    },
    plugins: [
        new HtmlWebpackPlugin(
            {
                template: path.join(__dirname, 'src', 'index.html'),
                filename: 'index.html' // 打包後產出的文件名
            }
        )
    ],
    // 啓動本地服務
    devServer: {
        port: 3000,
        // 啓動服務器的目錄
        contentBase: path.join(__dirname, 'dist')
    }
}

然後在package.json的scripts裏面加上一句"dev": "webpack-dev-server"

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "dev": "webpack-dev-server"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "html-webpack-plugin": "^3.2.0",
    "webpack": "^4.41.5",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.10.2"
  }
}

然後命令行執行npm run dev 

執行之後看到服務器開起來了,端口3000 ,運行結果如下,就是index.html的內容

有人會奇怪了,我這裏還沒有打包npm run build,沒在dist目錄看到文件,怎麼就可以訪問了?

過程描述一下就是:最後新增了"dev":"webpack-dev-server"之後,並沒有去npm run build而是直接去npm run dev,在dist打包目錄下只有bundle.js,沒有就index.html,但是居然運行成功了,能訪問index.html,why???

webpack-dev-server 生成 bundle.js 和 index.html ,放在內存中,直接作爲 server 的返回(因爲的這裏是本地服務器),而不是生成兩個文件。

細心的同學觀察到了,開啓服務器之後,我們只要一保存就馬上編譯,可以訪問最新內容,這是因爲webpack 結合 webpack-dev-server 會自動啓動了“自動刷新”功能。

 

6.webpack-babel(ES6的東西轉換成ES5)

相當於是ES6的編譯,將ES6轉換成ES5語法,因爲有的瀏覽器太落後,ES6語法無法識別

比如剛剛上面的例子,我們在index.js中修改一下代碼

const sum = (a, b) => {
    return a + b
}

const res = sum(10, 20)
console.log(res)

接着訪問localhost:3000/bundle.js

看到打包後還是ES6代碼如下

我們需要轉換成ES5的代碼,應該如何操作呢?

babel就是js的高級語法向低級語法轉變的工具,babel可以提供插件給webpack用

執行命令npm i @babel/core @babel/preset-env babel-loader

i就是install的簡寫,@就是組,@babel/core表示安裝bable組裏面的core模塊,env是babel的配置插件集合,babel-loader就是給webpack用的一個插件

接着在webpack-demo目錄下新建.babelrc文件(和webpack.config.js在同一目錄)

{
    "presets": [
        "@babel/preset-env"
    ]
}

接着修改webpack.config.js,主要是加上module模塊

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin') // 引進解析html的插件
module.exports = {
    mode: 'development', // production
    entry: path.join(__dirname, 'src', 'index.js'),//__dirname就是當前目錄(同一套代碼不同環境可能當前環境路徑字符串不一樣,__dirname能統一表示)
    //拼接src再拼接index.js,就能找到整個文件的入口
    output: {
        filename: 'bundle.js',
        path: path.join(__dirname, 'dist')
    },
    module: {
        rules: [
            { // 對js解析,只要以js結尾的,就都走一個loader轉義
                test: /\.js$/,
                loader: ['babel-loader'], // 只是babel-loader提供給webpack的一個插件,真正做轉義的還是@babel/core,所以要加上.babelrc的一個配置
                include: path.join(__dirname, 'src'), // 包含哪些目錄需要經過這個loader的轉義
                exclude: /node_modules/ // 這個已經轉義過了沒必要再次包含
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin(
            {
                template: path.join(__dirname, 'src', 'index.html'),
                filename: 'index.html' // 打包後產出的文件名
            }
        )
    ],
    // 啓動本地服務
    devServer: {
        port: 3000,
        // 啓動服務器的目錄
        contentBase: path.join(__dirname, 'dist')
    }
}

module模塊就是針對不同模塊做不通的解析

最後保存,執行npm run dev,再來訪問localhost:3000/bundle.js

看看這個sum函數,我們寫的ES6語法已經被轉義爲ES5語法了

那用我們之前講之前的例子試試,講index.js改爲

// 類
class Student {
    constructor(name, number) {
        this.name = name // 這個對象裏新增一個name賦值爲傳進來的name
        this.number = number
        // this.gender = 'male'
    }
    sayHi() {
        console.log(
            `姓名 ${this.name} ,學號 ${this.number}`
        )
    }
}
 
// 通過類 new 對象/實例
const xialuo = new Student('夏洛', 100)
console.log(xialuo.name)
console.log(xialuo.number)
xialuo.sayHi()
 
const madongmei = new Student('馬冬梅', 101)
console.log(madongmei.name)
console.log(madongmei.number)
madongmei.sayHi()

保存後再來訪問localhost:3000/bundle.js,結果如下,ES6的字符串寫法和class都變了,語法降級

 

7.webpack-ES6-Module(ES6的模塊化)

繼續接着上面講

單個導出

我們在src裏面新建a.js,去提供函數和變量,讓index.js去使用,用模塊化就是想用一個導出導入的過程

a.js(這裏講一個一個導出)

// 向外提供函數
export function fn() {
    console.log('fn')
}
// 向外提供變量
export const name = 'b'
// 向外提供對象
export const obj = {
    name: 'zhangsan'
}

index.js

import {fn, name, obj} from './a' // 類似於解構賦值
fn()
console.log(name)
console.log(obj)

運行結果 

 

一起導出

a.js

function fn() {
    console.log('fn')
}
const name = 'b'
const obj = {
    name: 'lisi'
}

export {
    fn,
    name,
    obj
} // 注意,這是ES6的寫法,不只侷限於模塊化,如果key和value一樣,簡寫一個就行了,ES5只能用key-value形式來寫
// ES5寫法如下
/*export {
    fn:fn,
    name:name,
    obj:obj
}*/

index.js不變

運行結果 

又或者a.js改爲如下,導出加了一個defalut,就沒法和解構賦值一樣來導入了

function fn() {
    console.log('fn')
}
const name = 'b'
const obj = {
    name: 'lisi'
}

export default {
    fn,
    name,
    obj
} // 注意,這是ES6的寫法,不只侷限於模塊化,如果key和value一樣,簡寫一個就行了,ES5只能用key-value形式來寫
// ES5寫法如下
/*export {
    fn:fn,
    name:name,
    obj:obj
}*/

index.js

import A from './a' // 導入的default對象給它一個名字叫A
A.fn()
console.log(A.name)
console.log(A.obj)

運行結果不變

 

8.webpack-配置生產環境

現在的webpack.config.js是開發環境的webpack配置,但是不能直接上線,體積又大運行又慢,接下來我們來看看怎麼配置一個生產環境的打包

我們在當前目錄新建一個生產環境的配置文件webpack.prod.js,prod就是production的簡寫

webpack.prod.js

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin') // 引進解析html的插件
module.exports = {
    mode: 'production', 
    entry: path.join(__dirname, 'src', 'index.js'),//__dirname就是當前目錄(同一套代碼不同環境可能當前環境路徑字符串不一樣,__dirname能統一表示)
    //拼接src再拼接index.js,就能找到整個文件的入口
    output: { // [contenthash]是根據代碼內容算出的hash值來追加命名,代碼不變命名就不變
        filename: 'bundle.[contenthash].js',
        path: path.join(__dirname, 'dist')
    },
    module: {
        rules: [
            { // 對js解析,只要以js結尾的,就都走一個loader轉義
                test: /\.js$/,
                loader: ['babel-loader'], // 只是babel-loader提供給webpack的一個插件,真正做轉義的還是@babel/core,所以要加上.babelrc的一個配置
                include: path.join(__dirname, 'src'), // 包含哪些目錄需要經過這個loader的轉義
                exclude: /node_modules/ // 這個已經轉義過了沒必要再次包含
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin(
            {
                template: path.join(__dirname, 'src', 'index.html'),
                filename: 'index.html' // 打包後產出的文件名
            }
        )
    ],
    // // 啓動本地服務
    // devServer: { // 要上線的代碼,本地服務不需要
    //     port: 3000,
    //     // 啓動服務器的目錄
    //     contentBase: path.join(__dirname, 'dist')
    // }
}

這裏的mode是production,如果不寫mode,會報警告提示,默認是production,打包出來的文件會被壓縮成一行,如果寫成development,打包出來的文件代碼就不會被壓縮。

接着我們需要去package.json去修改"build",因爲"build"的value還是"webpack",默認運行的開發環境配置webpack.config.js,它會去啓動我們寫的服務devServer,那我們怎麼辦呢?

來改一改package.json,我們上面講了,"build" : "webpack"就是"build" : "webpack --config webpack.config.js",而現在我們需要指定生產環境的配置,所以需要變成"build" : "webpack --config webpack.prod.js"

package.json

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config webpack.prod.js",
    "dev": "webpack-dev-server"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.8.4",
    "@babel/preset-env": "^7.8.4",
    "babel-loader": "^8.0.6",
    "html-webpack-plugin": "^3.2.0",
    "webpack": "^4.41.5",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.10.2"
  },
  "dependencies": {}
}

我們先刪掉dist目錄,防止之前的結果乾擾觀察,接着再次執行npm run build,現在運行的就是生產環境的配置webpack.prod.js了,我們來看看dist裏面是什麼

bundle.hash值.js,就是我們剛剛配置的[contenthash],從打包的log也能看到,至於爲什麼要這麼寫,我們在下一章講性能優化的時候再說,簡單講,爲了頁面運行的更快

我們可以看到bundle.hash值.js的內容都是經過壓縮的,壓縮後的代碼體積又小運行又快,下載也快,所以生產環境必須單獨配置。

 

關注、留言,我們一起學習。

 

===============Talk is cheap, show me the code================

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