前言
最近在看webpack4,深感知識淺薄,這兩天也一直在思考cli的配置,藉助一些別人的實踐,嘗試自己搭建vue的專案,這裡使用webpack4版本,之前我在網上查詢別人的vue專案搭建,但是都是webpack3的,所以寫了本文,如果有錯誤,或者有什麼問題,請大佬們指出
關於webpack的本文不會多說,請看webpack文件
關於本文的github地址vue-MYCLI
基礎版本
完成了基本的js vue css 的配置 基礎版本
完整版本
安裝了vue-router vuex less eslint,webpack配置已經調整完畢,基本可以使用 完整版本
前置知識
- 熟悉 webpack4
- 熟悉 vue
搭建基本骨架
npm init
安裝webpack4
npm install webpack webpack-cli --save-dev
在開始之前先實驗一下環境
根目錄新建檔案 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>Vue</title>
</head>
<body>
<script src="./src/mian.js"></script>
</body>
</html>
根目錄新建檔案 src/main.js
console.log("我是main");
根目錄新建檔案webpack.config.js
const path = require(`path`)
module.exports = {
entry: `./src/main.js`,
output: {
path: path.resolve(__dirname, dist),
filename: `index.js`
}
}
打包js檔案
npx webpack --config webpack.config.js
會看到一些報錯,只要構建成功就ok
這裡說明環境是沒有問題的
配置初始生成環境
開始安裝vue-loader吧
npm i webpack vue vue-loader -D //-D就是--save-dev
安裝完成後看輸出
提示安裝的依賴要安裝
npm install webpack css-loader -D
安裝完畢後新建src/app.vue
<template>
<div>
你好 {{ data }}
</div>
</template>
<script>
export default {
data(){
return {
data: "Vue"
}
}
}
</script>
<style scoped>
</style>
.vue檔案是無法直接執行的,需要在webpack裡面配置loader
這裡參照某課的老師的方法,html用webpack生成(後面說明)
在根目錄新建index.js 刪除index.html
import Vue from `vue`
import App from `./app.vue`
const root = document.createElement(`div`)
document.body.appendChild(root)
new Vue({
render: (h) => h(App)
}).$mount(root)
改寫webpack.config.js
const path = require(`path`)
module.exports = {
entry: path.resolve(__dirname, `src/index.js`), //關於path模組可以看看阮一峰的教程 http://javascript.ruanyifeng.com/nodejs/path.html#toc0
output: {
path: path.resolve(__dirname, `dist`),
filename: `index.js`
},
module: {
rules: [{
test: /.vue$/,
loader: `vue-loader`
}]
}
}
在package裡面新增指令碼
"build": "webpack --config webpack.config.js"
控制檯執行
npm run build
不出意外會報錯
這裡有2個問題,一個是沒有指定mode 一個是沒有引用vue的外掛
我們需要改寫webpack.config.js,在config裡面加一行
mode: `production`, //暫時指定為生產環境
再次執行npm run build
會報錯,需要安裝一個包
這個報錯,原本在vue-loader就有提示,不知道為什麼現在沒有,執行之前報錯
Error: [vue-loader] vue-template-compiler must be installed as a peer dependency, or a compatible compiler implementation must be passed via options
安裝vue-template-compiler
npm install vue-template-compiler -D
再再次執行npm run build
假如按步驟來不除意外這裡可以打包成功了~~~~
我們需要驗證打包檔案時候是否正確,所以這裡使用外掛HtmlWebpackPlugin,幫我們自動建立html檔案,並且在後續的hash檔名上很有用,具體可以看官方介紹
npm install html-webpack-plugin -D
改webpack.config.js程式碼
const path = require(`path`)
const { VueLoaderPlugin } = require(`vue-loader`)
var HtmlWebpackPlugin = require(`html-webpack-plugin`); //引入外掛
module.exports = {
mode: `production`, //暫時指定為生產環境
entry: path.resolve(__dirname, `src/index.js`), //關於path模組可以看看阮一峰的教程 http://javascript.ruanyifeng.com/nodejs/path.html#toc0
output: {
path: path.resolve(__dirname, `dist`),
filename: `index.js`
},
module: {
rules: [{
test: /.vue$/,
loader: `vue-loader`
}]
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin()
]
}
npm run build
打包一下,dist資料夾下面會有兩個檔案
打包Vue程式完成~~~~
至此完成了最基本的webpack配置
接下來我們要完成的的配置開發環境
配置開發環境
關於開發環境以及生成環境,webpack是需要區分的,根據文件模組,我決定在命令裡面指定模式,相應的就將開發環境以及生成環境分開,
這裡我使用的是提起基本的webpack配置使用webpack-merge
這個包來拼接我們webpack配置
npm i webpack-merge -D
修改配置檔案
將各各環境的程式碼區分開,webpack的結構是這樣的
webpack.config.base.js
const path = require(`path`)
const config = {
entry: path.resolve(__dirname, `../src/index.js`),
output: {
path: path.resolve(__dirname, `dist`),
filename: `index.js`
},
module: {
rules: [{
test: /.vue$/,
loader: `vue-loader`
}]
}
}
module.exports = config
webpack.config.build.js
const { VueLoaderPlugin } = require(`vue-loader`)
const HtmlWebpackPlugin = require(`html-webpack-plugin`)
const merge = require(`webpack-merge`)
const baseConfig = require(`./webpack.config.base`)
const config = merge(baseConfig ,{
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin()
]
})
module.exports = config
這裡配置開發環境就是重頭戲了,我們使用webpack-dev-server
webpack-dev-server是一個小型的Node.js Express
伺服器,程式碼都跑在記憶體裡面
安裝webpack-dev-server
npm install webpack-dev-server -D
webpack.config.dev.js
const webpack = require(`webpack`)
const merge = require(`webpack-merge`)
const baseConfig = require(`./webpack.config.base`)
const { VueLoaderPlugin } = require(`vue-loader`)
const HtmlWebpackPlugin = require(`html-webpack-plugin`)
const config = merge(baseConfig, {
devServer: {
port: `8000`,
host: `localhost`,
hot: true, //熱載入
//quiet: true //控制檯中不輸出打包的資訊
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin(),
new webpack.HotModuleReplacementPlugin()
]
})
module.exports = config
最後在package裡面新增指令碼
"build": "webpack --mode=production --config build/webpack.config.build.js",
"dev": "webpack-dev-server --mode=development --progress --config build/webpack.config.dev.js"
執行npm run dev
檢視控制檯
這就成功了,在瀏覽器裡面輸入http://localhost:8000/,修改app.vue檔案,實現了vue-cli的熱載入了~~~~
接下來完善一下,不能只有.vue檔案的loader,其他的webpack也要認識
我們配置一下圖片的loader,以及css的loader,同時css使用postcss進行預處理
url-loader 用於將檔案轉換為base64 URI file-loader是依賴loader
npm i url-loader file-loader -D
新增配置webpack.config.base.js>module>rules
{
test: /.(gif|png|jpg|svg)$/,
use: [{
loader: `url-loader`,
options: {
limit: 2048,
name: `resources/[path][name].[hash:8].[ext]`
}
}]
},
配置css(vue-cli裡面的實現非常友好,有機會可以去看看) 下面的是最簡單的配置
npm install css-loader -D
npm install vue-style-loader -D
npm install postcss-loader -D
新增配置webpack.config.base.js>module>rules (postcss不瞭解谷歌一下)
{
test: /.css$/,
use: [
`vue-style-loader`,
`css-loader`,
{
loader: `postcss-loader`,
options: {
sourceMap: true //啟用源對映支援,postcss-loader將使用其他載入器給出的先前源對映並相應地更新它
}
}
]
}
npm install autoprefixer -D
根目錄新建檔案postcss.config.js,安裝autoprefixer (自動新增瀏覽器字首)
const autoprofixer = require(`autoprefixer`)
module.exports = {
plugins: [
autoprofixer()
]
}
配置到這裡基本的圖片以及css就配置完成了,執行一下試試 npm run dev
我找src下面建立了assets/img/user.jpg
app.vue
<template>
<div>
你好 {{ data }}
<img src="./assets/img/user.jpg">
</div>
</template>
<script>
export default {
data(){
return {
data: "Vue Cli"
}
}
}
</script>
<style>
div{
font-size: 20px;
color: red;
}
img {
width: 100px;
}
</style>
實現了開發環境的圖片以及css的配置
打包一下試試
build後生成的目錄是這樣的
這不是我們想要的,webpack把程式碼,類庫,css都打包在一起,這樣不管是上線還是首屏載入都有影響,所以這裡我們要優化webpack
在處理之前想安裝一個可以幫助我們每次build之前自動刪除上次build生成的檔案的外掛
clean-webpack-plugin
這個外掛不知道為什麼,怎麼配置路徑都沒效果
這裡我使用rimraf來進行刪除(vue-cli也是使用rimraf,但是他是寫在程式碼裡面)
npm install rimraf -D
在package裡面變一下指令碼,讓打包之前幫我們刪除之前到打包檔案
"build-webpack": "webpack --mode=production --config build/webpack.config.build.js",
"delete": "rimraf dist",
"build": "npm run delete && npm run build-webpack"
分離打包css
它會將所有的入口 chunk(entry chunks)中引用的
*.css
,移動到獨立分離的 CSS 檔案
npm install extract-text-webpack-plugin@next -D
因為開發環境和生產環境不一樣
我們需要將css部分的程式碼分環境配置
- 將原先的css配置放到webpack.config.dev.js裡面
- 在webpack.config.build.js裡面重寫
module: {
rules: [{
test: /.css$/,
use: ExtractTextPlugin.extract({
fallback: "vue-style-loader",
use: [
`css-loader`,
{
loader: `postcss-loader`,
options: {
sourceMap: true
}
}
]
})
}]
},
這樣的話,我們開發環境不影響依舊是之前到模式,build的時候用ExtractTextPlugin幫我們分離非js檔案,實現css的分離打包
我們打包一下試試npm run build
分離js檔案
接下來是分離js檔案,就是將庫檔案以及我們的程式碼分離開,利於上線後的瀏覽器快取,程式碼會經常變,庫不會經常變
在webpack4之前js分離用的外掛是CommonsChunkPlugin,不過這外掛現在移除了,現在用的是optimization.splitChunks 來進行公共程式碼與第三方程式碼的提取,splitChunks引數如下
optimization: {
splitChunks: {
chunks: "initial", // 程式碼塊型別 必須三選一: "initial"(初始化) | "all"(預設就是all) | "async"(動態載入)
minSize: 0, // 最小尺寸,預設0
minChunks: 1, // 最小 chunk ,預設1
maxAsyncRequests: 1, // 最大非同步請求數, 預設1
maxInitialRequests: 1, // 最大初始化請求書,預設1
name: () => {}, // 名稱,此選項課接收 function
cacheGroups: { // 快取組會繼承splitChunks的配置,但是test、priorty和reuseExistingChunk只能用於配置快取組。
priority: "0", // 快取組優先順序 false | object |
vendor: { // key 為entry中定義的 入口名稱
chunks: "initial", // 必須三選一: "initial"(初始化) | "all" | "async"(預設就是非同步)
test: /react|lodash/, // 正則規則驗證,如果符合就提取 chunk
name: "vendor", // 要快取的 分隔出來的 chunk 名稱
minSize: 0,
minChunks: 1,
enforce: true,
reuseExistingChunk: true // 可設定是否重用已用chunk 不再建立新的chunk
}
}
}
}
官方包括這解釋,我並不是很看懂,所以打包策略並不是很好
在webpack.config.build.js>config
output: {
filename: `[name].[chunkhash:8].js`
},
optimization: {
splitChunks: {
chunks: "all",
cacheGroups: {
vendor: {
test: /node_modules/, //這裡雖然分離了,但是沒有做到按需引入,看官方配置也不是很明白
name: `vendors`,
chunks: `all`
}
}
},
runtimeChunk: true
}
build一下檢視目錄,可以看出程式碼與庫之間分離了
.gitignore
這裡處理一下git 新建檔案.gitignore
.DS_Store
node_modules/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
.editorconfig,
處理一下編譯器的統一配置
新建檔案 .editorconfig,(關於editorconfig,以及配置解釋)
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
還有一點要注意,假如沒有效果,vscode需要安裝一個外掛EditorConfig for VS Code
,其他編譯器不太清楚
.babelrc
處理一下ES6,以及js檔案的webpack的loader配置
今天裝了babel-loader8.0.0 報錯報一上午,心態都搞崩了,所以這裡我使用的是7版本
npm install babel-loader@7 babel-core babel-preset-env -D
在webpack.config.base.js>module>rules裡面新增程式碼
{
test: /.js$/,
exclude: /node_modules/,
loader: `babel-loader`
}
新建檔案 .babelrc
{
"presets": [
"env"
]
}
首先檢查開發環境
我新建了一個es6語法的js 匯入到app.vue裡面
執行結果
eslint
eslint的安裝相對簡單,可以看官方指南
npm install --save-dev eslint eslint-config-standard eslint-plugin-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-node
因為.vue檔案不會是純js程式碼,所以,我們需要安裝額外的解析的外掛
npm install eslint-plugin-html -D
然後我們配置eslint到我們的專案
在根目錄新建檔案.eslintrc
{
"extends": "standard",
"plugins": [
"html"
],
"rules": {
"no-new": "off" //因為new Vue但是eslint預設不許new 我們需要把這個關掉
}
}
在package裡面新增兩行指令碼
"lint": "eslint --ext .js --ext .jsx --ext .vue src/",
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"
現在執行npm run lint
即檢查專案
執行npm run lint-fix
,即是將不規範的地方修正
下一步我們配置到我們的webpack裡面讓執行的時候同時檢查程式碼
npm install eslint-loader babel-eslint -D
改寫配置檔案
{
"extends": "standard",
"plugins":[
"html"
],
"parser":"babel-eslint",
"rules": {
"no-new": "off"
}
}
在webpack.config.base裡面的module> rules 裡面加一個欄位
{
test: /.(vue|js|jsx)$/,
loader: `eslint-loader`,
exclude:/node_modules/,
enforce: `pre` //預處理
}
最後
至此,基本的vue專案骨架的搭建完畢了,後面還有vue-router 以及vuex less的安裝,請檢視我的github,當然他沒有vue-cli那麼強大,或許最大的益處是讓我們熟悉一個vue專案的大致webpack配置,當然我們可以一步一步的優化專案