基於Webpack4的Vue移動端開發環境搭建篇

NO IMAGE

寫在前面

在使用Vue開發單頁面的時候,我們大多數時候都是使用的官方CLI工具,現在的Vue CLI已經迭代到了4.X了,可以說很成熟穩定了,能滿足大多數要求,而且上手簡單。本著折騰摸索的精神,還是打算自己搭建一個開發環境,熟悉各個流程。

本文不涉及Webpack和babel知識的講解,建議瞭解一下Webpack的基本知識來看這篇文章會更好理解。這個在網上能找到很多教程。關於node.js和npm安裝在這裡也不再贅述,相信做前端開發這個是電腦必備的。

如果你在搭建過程中遇到不明的報錯,查看報錯信息並記錄排查,有時候相關的插件在更新過後使用方式會發生變化,有可能你按著我的配置走下來也報錯,那麼看看官方文檔(一般在github上查相關的倉庫即可)有沒有改變寫法,比如這次我配置的clean-webpack-plugin插件,以前的版本是不需要解構的,但是現在必須解構了,不然它會報錯並提示不是構造函數

大佬繞路輕噴。。。

更新:如果開發環境和生產環境都使用插件把CSS分離出來成為單獨的文件,那麼你在開發過程中會發現熱更新對CSS不生效,所以解決方法就是分離CSS僅配置在生產環境。給大家埋了個坑,sorry!

優化篇已經出爐:基於Webpack4的Vue移動端開發環境-優化篇

我的node.js及npm版本如下:

node -v
v12.13.0
npm -v
v6.12.0

開始

1、初始化一個項目

首先你要新建一個文件夾,我這兒叫 customized-vue-proj-mobile,然後在你的文件夾右鍵打開git bash輸入以下命令來初始化項目(需要安裝git,當然用cmd也是可以的):

npm init

執行完這個命令過後,會在目錄生成一個 package.json 的文件,我的文件內容如下:

{
"name": "customized-vue-proj-mobile",
"version": "1.0.0",
"description": "customized vue development environment",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/cookiepool/customized-vue-proj-mobile.git"
},
"keywords": [
"vue",
"mobile"
],
"author": "LEE",
"license": "MIT",
"bugs": {
"url": "https://github.com/cookiepool/customized-vue-proj-mobile/issues"
},
"homepage": "https://github.com/cookiepool/customized-vue-proj-mobile#readme"
}

這兒關於npm包管理也有很多知識點,這裡不在展開,建議大家可以自行了解下

這樣一個項目就先初始化完畢,接下來開始進入各種工具的安裝來完成環境的搭建。

2、安裝webpack

基於webpack的話肯定要先安裝好webpack才能繼續安裝後續的,所以先來安裝命令:

npm install webpack --save-dev
  • --save-dev 表示將包安裝信息放入到 package.jsondevDependencies 裡面,這個不會用於生產環境,-D 等效於 --save-dev
  • --save 表示將包安裝信息放入到 package.jsondependencies 裡面,這個會打包用於生產環境。-S 等效於 --save

接下來還需要安裝CLI,從webpack4開始必須要安裝webpack cli才能執行webpack相關的命令

npm install webpack-cli -D

接下來輸入 npx webpack --help 來測試webpack是否處於可用狀態,如果輸入這個命令後面板出現一大串配置幫助信息則代表webpack可用。

npx 可以直接調用項目內部安裝的模塊,而不需要全局安裝npm模塊,如果上面的命令你不使用npx你會發現系統顯示 bash: webpack: command not found


現在在項目目錄下新建一個src文件夾,裡面新建一個main.js文件,在裡面先隨便寫點js代碼。然後在建立一個build文件夾,並新建一個webpack.config.js配置文件。這樣一來我們的目錄結構就是這個樣子:

基於Webpack4的Vue移動端開發環境搭建篇

文件建好了但是還沒有內容,肯定跑不起來,接下來對webpack.config.js操作一番,這裡我不敘述具體過程了(#滑稽保命),直接貼代碼,裡面我寫了註釋:

// build/webpack.config.js
// node.js裡面自帶的操作路徑的模塊
const path = require('path');
module.exports = {
// 指定模式,這兒有none production development三個參數可選
// 具體作用請查閱官方文檔
mode: 'development',
// webpack打包的入口文件
entry: {
main: path.resolve(__dirname, '../src/main.js')
},
// webpack打包的輸出相關的額配置
output: {
// 打包過後的文件的輸出的路徑
path: path.resolve(__dirname, '../dist'),
// 打包後生成的js文件,帶hash值來保證文件的唯一性
filename: 'js/[name].[hash:4].js',
// 生成的chunk文件名
chunkFilename: 'js/[name].[hash:4].js',
// 資源的引用路徑(這個跟你打包上線的配置有關係)
publicPath: '/'
}
}

然後呢再把package.json改造一下,在scripts處添加一句 dev 這個命令:

"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack ./src/main.js --config ./build/webpack.config.js"
},

一頓操作過後,我們開始來試一試這個命令能不能用,在控制檯下輸入:

npm run dev

稍等一會兒就會出現以下信息,則代表我們打包輸出成功:

基於Webpack4的Vue移動端開發環境搭建篇

此時項目的結構變成這個樣子:

基於Webpack4的Vue移動端開發環境搭建篇

環境搭建到這兒只能說webpack配置正常了,還有許多額外東西需要配置,比如以下

  • babel,這個可以把ES6+轉換為低瀏覽器可用的ES5,以及對一些新API做polyfill處理
  • css預處理器,目前css預處理器有很多選擇,這裡我選擇了scss來做配置,當然你不使用css預處理器也是可以的。
  • 文件處理loader,這個主要是項目相關的圖片、字體、音視頻的處理。
  • html文件自動創建,你打包好的js文件等需要正確的導入html才能正常使用。
  • postcss,這個工具主要是處理css的,安裝相關的插件可以實現一些功能,比如自動添加css3的前綴,移動開發中用到的px-to-rem或者px-to-vw等等。
  • 熱更新功能,在開發過程中自動響應我們的修改並更新,不需要手動刷新。
  • 識別.vue文件,這個是讓webpack識別.vue文件並轉換成瀏覽器能使用的內容。
  • 集成vue-router和vuex,做單頁面路由不可少,狀態管理根據需要來引入即可,不是必須要配置的東西。

3、配置相關工具

3.1、ES6+轉ES5

首先來一波安裝命令,安裝好相關的依賴:

npm install babel-loader @babel-core @babel/preset-env -D
  • bable-loader 這個是用於webpack來處理babel的加載器,用於調用@babel/core的核心API來完成編譯。
  • @babel-core babel的核心,核心的api都在包含在這裡。
  • @babel/preset-env babel的一個預置環境。

參考我這篇文章來瞭解一下babel,當然社區上還有許多大佬寫的文章,多看幾篇可以瞭解的更加透徹。

  • 修改webpack.config.js

現在我們需要配置webpack來使其支持babel,這裡就需要使用到剛才安裝的babel-loader。在配置文件中加入以下代碼:

module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader'
}	
]
}
]
}
  • 在項目的根目錄新建babel.config.js

在文件中加入以下內容:

// babel.config.js
module.exports = {
// 配置預置環境
presets: [
// 使用的規則
"@babel/preset-env"
]
}

配置好後,去main.js裡面寫一些es6+的語法的js代碼,然後執行 npm run dev 你會發現dist目錄下生成的js文件語法都轉換成es5的了,但是promise卻沒有轉換,這裡我們還需要polyfill。

  • 配置polyfill並且按需引入

輸入以下命令安裝必須的依賴:

npm install [email protected] -S

安裝完畢後去babel.config.js修改代碼如下:

module.exports = {
// 配置預置環境
presets: [
// 使用的規則
["@babel/preset-env", {
// 這兒有false, entry, usage三個可選參數,usage可以按需引入polyfill
"useBuiltIns": "usage",
// 指定corejs版本
"corejs": 2
}]
]
}

這樣一來你的js就可以運行在低版本瀏覽器裡面了,比如Promise。

3.2、配置css預處理器

還是先安裝依賴

npm install sass-loader dart-sass css-loader style-loader -D
  • style-loader 該loader主要是把css解析到html的style標籤上。
  • css-loader 該loader用來解析css,注意在調用style-loader和css-loader時,css-loader要先於style-loader執行,不然會報錯,當你使用以下寫法時:
use: [{loader: 'style-loader'}, {loader: 'css-loader'}]

因為loader加載是從右往左加載。(為什麼從右往左加載 )這裡的編譯順序是先用css-loader將css代碼編譯,再交給style-loader插入到網頁裡面去。所以css-loader在右,style-loader在左。

  • sass-loader 該loader把scss或sass轉換為css。
  • dart-sass 這個工具類似於編譯器,轉換scss語法,結合到sass-loader使用,其實還有個node-sass可以使用。使用node-sass的話可以不用在webpack的配置文件裡面指定,只需要用npm安裝好node-sass即可,這兒我使用了dart-sass所以要在implementation中指定。

下載安裝好依賴過後,在配置文件 webpack.config.js 中的 module->rules 裡面加入以下代碼:

{
test: /\.(scss|sass)$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'sass-loader',
options: {
implementation: require('dart-sass')
}
}
]
}

3.3、創建Html文件以及相關處理

首先在項目目錄創建一個目錄public,裡面再創建一個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>customized-vue-proj-mobile</title>
</head>
<body>
<div id="app"></div>
</body>
</html>

此時目錄結構變成如圖所示

基於Webpack4的Vue移動端開發環境搭建篇

創建好文件後我們需要一個插件來處理html文件,只有js文件正常導入到html文件我們的項目才能運行起來,輸入以下命令來安裝 html-webpack-plugin

npm install html-webpack-plugin -D

安裝完成後,再webpack配置文件的plugins中加入以下代碼:

plugins: [
new htmlWebpackPlugin({
// 指定模板
template: path.resolve(__dirname, '../public/index.html'),
// 輸出的文件
filename: path.resolve(__dirname, '../dist/index.html')
})
]

3.4、配置字體、圖片等文件的處理

開發過程肯定會遇到很多媒體文件,特別是圖片,webapck有專門的loader來處理這些文件,先安裝好依賴:

npm install url-loader file-loader -D
  • url-loader和file-loader,這兩個其實功能差不多,url-loader的好處就是當文件小於我們指定的大小時,它可以把媒體文件轉換成base64編碼,這樣可以減少項目的圖片請求,提高訪問速度。

然後我們在webpack的配置文件中加入以下代碼:

{
test: /\.(jpe?g|png|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
// 當文件大於5kb時走file-loader相關的配置
limit: 5120,
// 這個參數要設置成false,不然生成圖片的路徑時[object Module]
esModule: false,
// 當文件大於5kb時走file-loader相關的配置
fallback: 'file-loader',
// 生成的路徑和文件名
name: 'images/[name].[hash:4].[ext]'
}
}
]
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 5120,
esModule: false,
fallback: 'file-loader',
name: 'media/[name].[hash:4].[ext]'
}
}
]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 5120,
esModule: false,
fallback: 'file-loader',
name: 'fonts/[name].[hash:4].[ext]'
}
}
]
},

以上我們就配置好了媒體文件相關的處理。

3.5、讓webpack識別vue文件

安裝依賴:

npm install vue-loader vue-template-compiler -D
  • vue-loader必須結合vue-template-compiler來使用,否則是不能完成轉換的。

首先配置module裡面的內容:

{
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
options: {
compilerOptions: {
preserveWhitespace: false
}
}
}
]
}

配置裡面有個compilerOptions的參數preserveWhitespace為false,這個意思是當它的值為true時意味著編譯好的渲染函數會保留所有 HTML 標籤之間的空格。如果設置為 false,則標籤之間的空格會被忽略。這能夠略微提升一點性能但是可能會影響到內聯元素的佈局。具體參考此處:鏈接

配置好module後我們還要引入插件,這個是必須的

// 引入vue-loader插件
const VueLoaderPlugin = require('vue-loader/lib/plugin');
// 添加到plugins中
new VueLoaderPlugin()

具體的大家可以參考此處:鏈接

然後我們還需要配置alias,這樣可以減少路徑過長引用的麻煩:

resolve: {
alias: {
// 寫了這句,我們可以這樣寫代碼 import Vue from 'vue', 並且引入的是vue/dist/vue.runtime.esm.js這個版本,不然默認引入的是vue.js。這個在github的vue官方倉庫dist目錄下有解釋。
'vue$': 'vue/dist/vue.runtime.esm.js',
// 寫了這句,我們可以這樣寫代碼 import api from '@/api/api.js',省去到處找路徑定位到src的麻煩
'@': path.resolve(__dirname, '../src')
},
// 添加一個 resolve.extensions 屬性,方便我們引入依賴或者文件的時候可以省略後綴
// 我們在引入文件時可以這樣寫 import api from '@/api/api'。
extensions: ['*', '.js', '.vue']
},

3.6、配置postcss

這個地方我配置了三個插件,autoprefixer、postcss-pxtorem、postcss-px-to-viewport,後兩個你只需要配置其中一個即可,主要看你開發使用的rem還是vw,自行選擇即可。

npm install postcss-loader autoprefixer postcss-pxtorem postcss-px-to-viewport -D
  • postcss-loader 負責postcss相關的操作。
  • autoprefixer 為瀏覽器添加不同的css3前綴。
  • postcss-pxtorem px自動轉換為rem。
  • postcss-px-to-viewport px自動轉換為vw|vh。

安裝好依賴過後,在項目的根目錄建立文件 postcss.config.js,然後在文件中輸入以下內容:

module.exports = {
plugins: {
// 這個工具可以實現自動添加CSS3前綴
"autoprefixer": {},
// 如果你使用rem來實現移動端多設備適配,這個工具可以把px轉換為rem
/* "postcss-pxtorem": {
rootValue: 37.5, // 指定轉換倍率,我現在設置這個表示1rem=37.5px;
propList: ['*'], // 屬性列表,表示你要把哪些css屬性的px轉換成rem,這個*表示所有
minPixelValue: 1, // 需要轉換的最小值,一般1px像素不轉換,以上才轉換
unitPrecision: 6, // 轉換成rem單位的小數點後的保留位數
selectorBalckList: ['van'], // 匹配不被轉換為rem的選擇器
replace: true, // 替換包含rem的規則,而不是添加回退
mediaQuery: false // 允許在媒體查詢中轉換px
}, */
// 如果你使用vw來實現移動端多設備適配,這個工具可以把px轉換為vw
"postcss-px-to-viewport": {
unitToConvert: 'px', // 把什麼單位轉換成vw
viewportWidth: 750, // 這個可以按照你的設計稿來設置,是750就設置750,375就設置成375
unitPrecision: 6, // 轉換成vw單位的小數點後的保留位數
propList: ['*'], // 屬性列表,表示你要把哪些css屬性的px轉換成vw,這個*表示所有
viewportUnit: 'vw', // 使用的單位,目前可選單位有vw,vh。一般我們都有vw
fontViewportUnit: 'vw', // 字體使用的單位
selectorBlackList: [], // 匹配不被轉換為vw的選擇器
minPixelValue: 1, // 需要轉換的最小值,一般1px像素不轉換,以上才轉換
mediaQuery: false, // 允許在媒體查詢中轉換px
replace: true, // 替換包含vw的規則,而不是添加回退
exclude: [], // 忽略一些文件,比如“node_modules”,可以是正則表達式
landscape: false,  // ......
landscapeUnit: 'vw', // ......
landscapeWidth: 568 // ......
}
}
}

然後呢,webpack配置加上:

{
test: /\.(scss|sass)$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'sass-loader',
options: {
implementation: require('dart-sass')
}
},
{
loader: 'postcss-loader'
}
]
}

3.7、配置熱更新功能

安裝依賴:

npm install webpack-dev-server -D

安裝完成後,進行如下的配置:

// 引入webpack
const webpack = require('webpack');
// 配置devServer
devServer: {
// 默認情況不設置這個只能通過localhost:9000來訪問,現在可以通過本機局域網ip來訪問,
// 比如192.168.12.21:9000,手機在這個局網內也可以訪問
host: '0.0.0.0',
hot: true,
port: 9200,
contentBase: './dist'
}
// 配置plugins
new webpack.NamedModulesPlugin(), // 輔助HotModuleReplacementPlugin插件
new webpack.HotModuleReplacementPlugin(), // 啟用熱更新必須的

4、定義環境變量

這個主要是定義這個玩意兒 process.env.NODE_ENV ,定義好這個我們一般可以來判斷什麼樣的環境執行什麼樣的代碼,我們知道webpack的打包環境和開發環境配置一般是不一樣的,這裡不展開,後面會講。比如我們在入口main.js裡面這樣來寫代碼判斷:

if(process.env.NODE_ENV === 'development'){ 
//開發環境 do something
}else if(process.env.NODE_ENV === 'production') {
//生產環境 do something
}

那麼定義這個環境怎麼操作呢,第一種是藉助webpack的插件DefinePlugin,

  • 使用DefinePlugin
    我們在plugins裡面加入以下代碼:
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development')
}
}),

那麼我們最終打包過後訪問到的process.env.NODE_ENV的值就是development。

另一種使用webpack4自己集成了的環境判斷,我們只需要在配置文件裡面聲明mode即可,推薦使用這種

  • 使用webpack4的mode參數
module.exports = {
// 有none production development三個參數可選,不設置mode的話默認的process.env.NODE_ENV值為production
mode: "development",
entry: {}
.....
}

有了上面的mode設置,我們照樣能取到process.env.NODE_ENV的值。
關於process.env.NODE_ENV的知識點這裡有幾篇文章可以參考:

鏈接-1
鏈接-2
鏈接-3

5、集成Vue全家桶

安裝依賴

npm install vue vuex vue-router -S

安裝完依賴過後,在src目錄下新建一個App.vue的文件。寫入以下代碼:

<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss">
</style>

在src下再新建router、store兩個目錄,再目錄下分別新建router.js和store.js。順便再把其他文件夾也建好,如components、assets、views。現在我的目錄結構如下圖所示:

基於Webpack4的Vue移動端開發環境搭建篇

main.js裡面修改為如下代碼:

import Vue from "vue";
import App from "./App.vue";
import router from "./router.js";
new Vue({
router,
render: h => h(App)
}).$mount("#app");

建好這些文件過後其實後面的代碼書寫就跟官方腳手架搭建好的寫法一樣,這裡就不在演示其它文件的代碼怎麼書寫了,到時可以參考我的源代碼。

這兒引入vue-router和vuex過後,根據官方文檔做好配置即可開始測試,我這個只測試了vue和vue-router的功能正常,vuex暫時只建立了文件,但未進行實際引入測試。後面我會把源代碼提交到github供大家參考

這個時候,我們直接npm run dev的話會打包,所以我們需要把package.json的scripts中的dev改成如下的代碼:

"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --config ./build/webpack.config.js"
},

走到這步,如果你做好了前面的工作,理論上這兒執行npm run dev後就能看到效果了,我這兒的效果如圖所示:

基於Webpack4的Vue移動端開發環境搭建篇

6、區分開發環境和生產環境

做單頁面開發我們都知道,開發環境和生產環境是不太一樣的,平時使用官方cli時開發命令用的npm run dev,而打包發佈時npm run build。這裡面的配置肯定是存在區別的。

現在在build目錄下新建webpack.dev.js和webpack.prod.js兩個文件,用來區分開發環境和生產環境。同時把開發環境和生產環境通用的配置都寫在webpack.config.js裡面。

  • 開發環境

1、webpack的mode屬性值設置為development,開啟這個不會壓縮代碼。
2、需要webpack-dev-server和熱更新。
3、css不用提取到單獨文件並壓縮(當然你也可以提出來)
4、不需要構建前清除上一次構建內容
5、不需要打包分析

  • 生產環境

1、webpack的mode屬性值設置為production,開啟這個會壓縮代碼。
2、不需要webpack-dev-server和熱更新。
3、css要提取到單獨文件並壓縮
4、需要構建前清除上一次構建內容
5、需要打包分析

好了,大概瞭解了區別後,我們還需要單獨安裝其他沒有的依賴,先來波安裝命令,一把梭:

npm i clean-webpack-plugin copy-webpack-plugin @intervolga/optimize-cssnano-plugin mini-css-extract-plugin webpack-merge webpack-bundle-analyzer -D
  • clean-webpack-plugin 這個插件主要是用來清除上一次打包的內容,因為每次打包文件後面會生成新的hash值,不及時清除dist目錄會累積很多文件,還容易造成不必要的麻煩。
  • copy-webpack-plugin 有時候我們存在靜態資源,也就是不參與打包的文件,這時候我們就需要這個插件來實現拷貝,保證資源可訪問。
  • @intervolga/optimize-cssnano-plugin 分離出來的css文件進行壓縮。
  • mini-css-extract-plugin 用於把css單獨分離出來。
  • webpack-merge 合併webpack配置的插件。
  • webpack-bundle-analyzer 打包過後可以看到各個js文件所佔的大小以及在項目中的比例。

接下來修改相關的文件

6.1、webpack.config.js

注:這兒我把miniCssExtractPlugin放在通用配置文件裡面了,開發和生產都使用,這裡格式有點亂了

  • 更新:由於單獨提取文件在開發環境會出現不可及時更新的問題,這兒我還是改成開發環境不提取,生產環境才提取CSS文件。
// build/webpack.config.js
// node.js裡面自帶的操作路徑的模塊
const path = require("path");
// 引入htmlWebpackPlugin自動導入js文件
const htmlWebpackPlugin = require('html-webpack-plugin');
// 引入vue-loader插件
const VueLoaderPlugin = require('vue-loader/lib/plugin');
// 拷貝靜態資源
const copyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
// webpack打包的入口文件
entry: {
main: path.resolve(__dirname, "../src/main.js")
},
// webpack打包的輸出相關的額配置
output: {
// 打包過後的文件的輸出的路徑
path: path.resolve(__dirname, "../dist"),
// 打包後生成的js文件,帶hash值來保證文件的唯一性
filename: "js/[name].[hash:4].js",
// 生成的chunk文件名
chunkFilename: "js/[name].[hash:4].js",
// 資源的引用路徑(這個跟你打包上線的配置有關係)
publicPath: "/"
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader'
}	
]
},
{
test: /\.css$/,
// 這兒組件庫的css一般都是處理過的,我們使用一般的loader即可
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
}
]
},
{
test: /\.(jpe?g|png|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
// 當文件大於5kb時走file-loader相關的配置
limit: 5120,
// 這個參數要設置成false,不然生成圖片的路徑時[object Module]
esModule: false,
// 當文件大於5kb時走file-loader相關的配置
fallback: 'file-loader',
// 生成的路徑和文件名
name: 'images/[name].[hash:4].[ext]'
}
}
]
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 5120,
esModule: false,
fallback: 'file-loader',
name: 'media/[name].[hash:4].[ext]'
}
}
]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 5120,
esModule: false,
fallback: 'file-loader',
name: 'fonts/[name].[hash:4].[ext]'
}
}
]
},
{
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
options: {
compilerOptions: {
preserveWhitespace: false
}
}
}
]
}
]
},
plugins: [
new htmlWebpackPlugin({
// 指定模板
template: path.resolve(__dirname, '../public/index.html'),
// 輸出的文件
filename: path.resolve(__dirname, '../dist/index.html')
}),
new VueLoaderPlugin(),
// 新建miniCssExtractPlugin實例並配置
new miniCssExtractPlugin({
filename: 'css/[name].[hash:4].css',
chunkFilename: 'css/[name].[hash:4].css'
}),
// 壓縮css
new optimizeCssnanoPlugin({
sourceMap: true,
cssnanoOptions: {
preset: ['default', {
discardComments: {
removeAll: true,
},
}],
},
}),
// 拷貝靜態資源
new copyWebpackPlugin([{
from: path.resolve(__dirname, '../public'),
to: path.resolve(__dirname, '../dist')
}])
],
resolve: {
alias: {
// 寫了這句,我們可以這樣寫代碼 import Vue from 'vue'
'vue$': 'vue/dist/vue.runtime.esm.js',
// 寫了這句,我們可以這樣寫代碼 import api from '@/api/api.js',省去到處找路徑定位到src的麻煩
'@': path.resolve(__dirname, '../src')
},
// 添加一個 resolve.extensions 屬性,方便我們引入依賴或者文件的時候可以省略後綴
// 我們在引入文件時可以這樣寫 import api from '@/api/api'。
extensions: ['*', '.js', '.vue']
}
};

6.2、webpack.dev.js

// build/webpack.dev.js
// 引入webpack
const webpack = require('webpack');
// 引入webpack通用配置
const webpackCommonConfig = require('./webpack.config.js');
// 引入配置合併插件
const merge = require('webpack-merge');
module.exports = merge(webpackCommonConfig, {
// 指定模式,這兒有none production development三個參數可選
// 具體作用請查閱官方文檔
mode: "development",
module: {
rules: [
{
test: /\.(scss|sass)$/,
use: [
{
loader: 'style-loader', // 開發環境還是使用style-loader,不然無法及時響應樣式變化
},
{
loader: 'css-loader',
},
{
loader: 'sass-loader',
options: {
implementation: require('dart-sass')
}
},
{
loader: 'postcss-loader'
}
]
}
]
},
plugins: [
// 輔助HotModuleReplacementPlugin插件
new webpack.NamedModulesPlugin(),
// 啟用熱更新必須的
new webpack.HotModuleReplacementPlugin(),
],
devServer: {
// 默認情況不設置這個只能通過localhost:9000來訪問,現在可以通過本機局域網ip來訪問,
// 比如192.168.12.21:9000,手機在這個局網內也可以訪問
host: '0.0.0.0',
hot: true,
port: 9200,
contentBase: './dist'
}
});

6.3、webapck.prod.js

// build/webpack.prod.js
// 引入清除打包後文件的插件(最新版的需要解構,不然會報不是構造函數的錯,而且名字必須寫CleanWebpackPlugin)
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// 引入配置合併插件
const merge = require('webpack-merge');
// 引入通用配置
const webpackCommonConfig = require('./webpack.config.js');
// 分析打包後模塊分析插件
const webpackBundleAnalyzer = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = merge(webpackCommonConfig, {
// 指定模式,這兒有none production development三個參數可選
// 具體作用請查閱官方文檔
mode: "production",
module: {
rules: [
{
test: /\.(scss|sass)$/,
use: [
{
loader: miniCssExtractPlugin.loader, // 使用miniCssExtractPlugin.loader代替style-loader
},
{
loader: 'css-loader',
},
{
loader: 'sass-loader',
options: {
implementation: require('dart-sass')
}
},
{
loader: 'postcss-loader'
}
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new webpackBundleAnalyzer({
analyzerMode: 'static'
}),
]
});

配置好相關文件後我們再修改下package.json中的scripts:

"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --config ./build/webpack.dev.js",
"build": "webpack --config ./build/webpack.prod.js"
},

2019-12-30更新

新增

增加代碼風格檢測(針對Vue+VSCode)

首先是Vue項目的話,需要安裝VSCode插件。

  • Vetur 用來識別Vue文件的
  • ESLint JS代碼規範檢測
  • Prettier-Code formatter 代碼風格自動格式化

這兒呢我們主要是配置Eslint,這個配置好後你的項目在開發過程中會有更細緻的代碼風格相關的提示,規則可以自定義,這樣可以方便不同公司團隊有針對性的自行配置。(這兒我選擇了standard規範)

首先我們需要安裝各種依賴,先來這幾個核心的

npm install eslint eslint-plugin-vue -D
  • eslint的核心。
  • eslint-plugin-vue vue官方出品的用於檢測.vue文件裡面的template、js這些。

接下來周邊的擴展:

npm install babel-eslint eslint-config-standard eslint-plugin-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-node -D
  • babel-eslint 對所有有效的babel代碼進行lint處理。
  • eslint-config-standard 包含了標準的eslint代碼風格。當然你還可以選擇其它的標準,比如google的eslint-config-google,愛彼迎的eslint-config-airbnb,這些插件都有前置依賴要求,可以用這個命令來查看前置依賴,以standard為例npm info "[email protected]" peerDependencies,這就是為啥上面要安裝import、promise、node這些。
基於Webpack4的Vue移動端開發環境搭建篇

  • eslint-plugin-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-node eslint-config-standard的前置依賴

安裝完畢後進入下一步,在項目根目錄新建一個 .eslintrc 文件。

touch .eslintrc

在文件裡面加入以下配置信息,這只是一個最基本的配置。

{
"root": true,
"env": {
"node": true,
"browser": true
},
"parserOptions": {
"parser": "babel-eslint",
"sourceMap": "module",
"ecmaVersion": 7
},
"extends": [
"plugin:vue/essential",
"standard"
],
"rules": {
"semi": "off", // 關閉語句後不能使用分號的規則
"space-before-function-paren": "off", // 關閉函數函數聲明在小括號前必須加空格的規則
"no-trailing-spaces": "off", // 關閉禁用行尾空格
"eol-last": "off", // 關閉要求或禁止文件末尾存在空行
"comma-dangle": "warn" // 出現拖尾逗號僅反饋警告,而不是報錯
}
}

我們還可以配置實時編譯校驗,在webpack的module->rule中加入以下loader(在webpack.dev.js中)

安裝eslint-loader

npm install eslint-loader -D

做好配置

module: {
rules: [
{
// 這個用來前置執行改loader,我們知道loader是有加載次序的,而且加載次序是有要求的,這個表示在js、vue相關的loader之前執行eslint-loader
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /node_modules/
}
]
}

添加完畢後可以到你的項目做個測試,看會不會報警告或者錯誤,比如定義一個未使用的變量。

let temp;

你還可以在項目根目錄建一個 .eslintignore 文件,用來忽略你不想檢查的文件或者文件夾,比如我忽略掉node_modules文件夾

node_modules

如果你不想手動修改eslint拋出的規則報錯,可以藉助腳本命令,在package.json中加入如下代碼:

scripts: {
"lint": "eslint --fix --ext .js,.vue src"
}

然後執行:

npm run lint

這個基本能修復大多數格式問題,不能修復的就只能手動修改了。

這樣一來eslint就配置完畢了,想要更加細緻的規則配置請參考官方文檔。

git commit時開啟eslint檢測

我們還可以做得更加嚴格點,那就是代碼不符合規範的不讓提交。(這裡藉助了git hooks,詳情見此處:鏈接地址)

首先我們需要安裝一個依賴:

npm install husky -D

然後在根目錄新建一個文件 .huskyrc。在裡面加入以下代碼:

{
"hooks": {
"pre-commit": "npm run lint:commit"
}
}

再在package.json裡面新加一個script:

  "lint:commit": "eslint --ext .js,.vue src"

這樣一來你每次提交代碼時都會先檢查代碼樣式。

  • 做個補充,eslint默認的錯誤提示看著不夠友好,可以藉助這個工具來轉換下格式

安裝一下依賴:

npm install eslint-friendly-formatter -D

在webpack.config.js中加入以下代碼:

{
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /node_modules/,
options: {
formatter: require('eslint-friendly-formatter')
}
}

將錯誤展示在瀏覽器頁面上

一般我們的報錯只能在瀏覽器的console面板上看,我們可以直接把他展示到界面上。

在devServer屬性上添加overlay:

devServer: {
host: '0.0.0.0',
hot: true,
port: 9200,
contentBase: './dist',
clientLogLevel: "error", // 關閉在瀏覽器控制檯顯示消息的功能,可能的值有 none, error, warning 或者 info(默認值)。這裡我設置為只顯示錯誤消息
overlay: {
errors: true,
warnings: true
}
}

最後

相關配置到這兒就結束了,後期會繼續更新優化方面的內容,如代碼拆分這些,本篇只是如何來搭建一個環境並跑起來,並沒有優化相關的內容。如有錯誤還請大家交流指出,覺得不錯的話點個贊再走吧!

相關代碼我已經提交到倉庫了,鏈接地址

相關文章

談談Swift中的枚舉內存佈局

ThreadLocal的進化——TransmittableThreadLocal

為什麼每一個爬蟲工程師都應該學習Kafka

SpringSecurityOAuth2開發者指南譯