目錄
1.關於開發環境
面試官想通過開發環境瞭解候選人的實際工作情況,而開發環境的工具能體現工作產出的效率,這些問題會以聊天形式爲主,不會問具體的問題。
在這裏1、2、3、4點我都是隻是概述總結,沒有細講,因爲每個都是長篇大論而且網上搜得到
5、6、7、8是從0到1搭建webpack環境並且運行,如果有一點webpack經歷,這應該是一個很好的複習
2.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================