前言
今天的內(nèi)容是如何從零搭建基于Webpack4的Vue前端腳手架碾篡,如有問題虱而,歡迎來交流啊开泽!
整個過程大致分為以下幾個步驟:
- 搭建cvue-cli v1.0牡拇,就是一個最基本的架子,目標是可以成功本地運行和打包出文件穆律。
2.搭建cvue-cli v2.0惠呼,把vue以及l(fā)ess什么的都安上,目標是運行后可以看到類似官方腳手架那樣的頁面峦耘。
3.搭建cvue-cli v3.0剔蹋,最后在做一些優(yōu)化工作,css該分離的分離辅髓,文件該壓縮的壓縮
注意:如需要泣崩,歡迎轉(zhuǎn)載,但請注明轉(zhuǎn)載文章出處 \o(^o^)o
正文
搭建cvue-cli v1.0
1.初始化項目
npm init -y
2.初始化項目的目錄結(jié)構(gòu)洛口,結(jié)構(gòu)如下:
3.修改package.json文件
{
"name": "cvue-cli",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"dev": "webpack --config build/webpack.base.config.js --mode development",
"build": "webpack --config build/webpack.base.config.js --mode production"
},
"keywords": [],
"author": "",
"license": "ISC"
}
- 配置webpack.base.config.js
// 先安裝幾個輔助插件
npm install --save-dev clean-webpack-plugin html-webpack-plugin webpack webpack-cli
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugins = require('html-webpack-plugin')
module.exports = {
// 入口js路徑矫付,注意這里是./而不是../,下面HtmlWebpackPlugins的template屬性也一樣绍弟,我理解的是這里的路徑都是相對于項目根目錄
entry: './src/main.js',
// 配置編譯文件輸出路徑
output: {
// 以原始文件名的輸出文件名
filename: '[name].js',
path: path.resolve(__dirname, '../dist')
},
plugins: [
// 自動清空dist文件夾
new CleanWebpackPlugin(),
// 設(shè)置html模板生成路徑
new HtmlWebpackPlugins({
filename: 'index.html', // 輸出的html文件名技即,默認index.html
template: './public/index.html', // html模板路徑,注意這里也是./而不是../
chunks: ['main'] // 指定在html自動引入的js打包文件
})
]
}
- 修改main.js文件
document.write('hello cvue-cli樟遣!')
- 運行npm run build打包編譯文件而叼,打包完的目錄結(jié)構(gòu)如下
瀏覽器打開index.html文件,頁面中出現(xiàn) “hello cvue-cli豹悬!”葵陵,恭喜你成功地邁出了第一步,下面再接再厲瞻佛!
- 下面搭建開發(fā)環(huán)境的熱監(jiān)測服務(wù)器
npm install --save-dev webpack-dev-server
- 修改package.json中的dev命令
"dev": "webpack-dev-server --config build/webpack.base.config.js --open --mode development",
9.修改webpack.base.config.js文件
// 添加如下內(nèi)容
devServer: {
contentBase: './dist', //指定需要提供給本地服務(wù)的內(nèi)容的路徑脱篙,默認加載index.html文件,可根據(jù)需要修改
port: 8080, // 端口設(shè)置伤柄,默認8080
hot: true // 開啟熱更新绊困,瀏覽器自動刷新
}
- 將webpack配置進行分離,分為本地開發(fā)環(huán)境和生產(chǎn)環(huán)境
// 首先安裝插件
npm install --save-dev webpack-merge
webpack.base.config.js保留如下內(nèi)容(注意:這里修改了js的打包輸出路徑):
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugins = require('html-webpack-plugin')
module.exports = {
// 入口js路徑适刀,注意這里是./而不是../秤朗,下面HtmlWebpackPlugins的template屬性也一樣,我理解的是這里的路徑都是相對于項目根目錄
entry: './src/main.js',
// 配置編譯文件輸出路徑
output: {
// 以原始文件名的輸出文件名
filename: 'js/[name].js',
path: path.resolve(__dirname, '../dist')
},
plugins: [
// 自動清空dist文件夾
new CleanWebpackPlugin(),
// 設(shè)置html模板生成路徑
new HtmlWebpackPlugins({
filename: 'index.html', // 輸出的html文件名笔喉,默認index.html
template: './public/index.html', // html模板路徑取视,注意這里也是./而不是../
chunks: ['main'] // 指定在html自動引入的js打包文件
})
]
}
webpack.dev.config.js修改為如下內(nèi)容:
const merge = require('webpack-merge')
const baseConfig = require('./webpack.base.config')
module.exports = merge(baseConfig, {
devServer: {
contentBase: './dist', //指定需要提供給本地服務(wù)的內(nèi)容的路徑硝皂,默認加載index.html文件,可根據(jù)需要修改
port: 8080, // 端口設(shè)置作谭,默認8080
hot: true // 開啟熱更新稽物,瀏覽器自動刷新
}
})
webpack.prod.config.js修改為如下內(nèi)容:
const merge = require('webpack-merge')
const baseConfig = require('./webpack.base.config')
module.exports = merge(baseConfig, {
// 方便追蹤源代碼錯誤
devtool: 'source-map'
})
然后,我們修改下package.json中的dev和build命令:
"scripts": {
"dev": "webpack-dev-server --config build/webpack.dev.config.js --open --mode development",
"build": "webpack --config build/webpack.prod.config.js --mode production"
},
最后折欠,嘗試運行下npm run dev 和 npm run build贝或,看運行結(jié)果是否正常!
搭建cvue-cli v2.0
- 首先安裝相關(guān)依賴包(每個具體的作用就不介紹了怨酝,可自行百度)
npm install --save vue
npm install --save-dev vue-loader vue-template-compiler vue-style-loader css-loader
- 修改webpack.base.config.js文件傀缩,添加相應(yīng)loader的配置規(guī)則,以及在plugins中添加vue-loader官方提供的魔法插件
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader']
},
// 它會應(yīng)用到普通的 `.css` 文件以及 `.vue` 文件中的 `<style>` 塊农猬,因為魔法插件VueLoaderPlugin
{
test: /\.css$/,
use: ['vue-style-loader', 'css-loader']
}
]
}
const VueLoaderPlugin = require('vue-loader/lib/plugin')
plugins: [
// 將定義過的其它規(guī)則復制并應(yīng)用到 .vue 文件里相應(yīng)語言的塊
new VueLoaderPlugin()
]
-
添加App.vue文件
<template>
<div id="app"></div>
</template>
<script>
export default {
data() {
return {
message: 'hello cvue-cli'
}
}
}
</script>
<style>
#app {
color: red;
}
</style>
- 下面修改main.js文件赡艰,引入Vue的使用
import Vue from 'vue'
import App from './APP.vue'
new Vue({
el: '#app',
render: h => h(App)
})
注意:
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
如果在創(chuàng)建根實例時,采用上面的寫法斤葱,瀏覽器會提示下面的錯誤:
引起該錯誤的原因和解決方法請查看下面的鏈接:
https://blog.csdn.net/wxl1555/article/details/83187647
- 修改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>cvue-cli</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
然后執(zhí)行npm run dev慷垮,如果頁面中出現(xiàn)了message對應(yīng)的值,且字體為紅色揍堕,說明vue單文件起作用了料身!
- 下面安裝file-loader和url-loader
// 因為url-loader基于file-loader,所以都要安裝衩茸。
// url-loader在file-loader上進行擴展芹血,當文件小于多少KB時進行base64轉(zhuǎn)換
npm install --save-dev file-loader url-loader
- 在webpack.base.config.js中添加文件loader的規(guī)則
// 圖片文件處理
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000
}
}
},
// 音頻文件
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000
}
}
},
// 字體文件
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000
}
}
}
-
在src目錄下創(chuàng)建assets文件夾,用來存放我們的圖片(這里使用vue官方logo)楞慈,然后修改App.vue文件
<template>
<div id="app">
<img src="./assets/logo.png">
<h1>{{message}}</h1>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
message: 'hello cvue-cli'
}
}
}
</script>
<style>
#app {
text-align: center;
}
</style>
最后運行 npm run dev幔烛,如果瀏覽器中出現(xiàn)如下的樣子,那么恭喜你囊蓝,馬上就可以完成cvue-cli v2.0的搭建了饿悬。怎么樣?心里是不是有點小激動呢聚霜?別急狡恬,下面我們需要繼續(xù)完善。
- 下面安裝和使用vue-router
安裝vue-router
npm install --save vue-router
添加相關(guān)文件蝎宇,項目結(jié)構(gòu)如下
hello-router.vue文件
<style>
.wrapper > h1 {
color: blue;
}
</style>
<template>
<div class="wrapper">
<h1>{{mesg}}</h1>
</div>
</template>
<script>
export default {
data() {
return {
mesg: "hello router"
}
}
}
</script>
index.js文件
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
const routes = [{
path: '/',
name: 'hello-router',
component: () => import('../components/hello-router.vue')
}]
const router = new Router({
routes
})
export default router
main.js文件
import Vue from 'vue'
import App from './APP.vue'
import router from './router/index'
new Vue({
el: '#app',
router,
render: h => h(App)
})
然后運行npm run dev弟劲,出現(xiàn)下圖:
- 安裝使用css預(yù)處理器-less
安裝less和less-loader
npm install --save-dev less less-loader
在webpack.base.config.js中配置less-loader
{
test: /\.less$/,
use: ['vue-style-loader', 'css-loader', 'less-loader']
}
添加hello-router.less文件
.wrapper {
h2 {
color: green;
}
}
修改hello-router.vue
<style lang="less">
@import './hello-router.less';
.wrapper {
h1 {
color: purple;
}
}
</style>
<template>
<div class="wrapper">
<h1>{{mesg}}</h1>
<h2>{{mesg2}}</h2>
</div>
</template>
<script>
export default {
data() {
return {
mesg: 'hello router',
mesg2: 'i am mesg2!'
}
}
}
</script>
運行npm run dev,效果如下
下面我們在運行npm run build姥芥,然后在看下本地打包后的文件是否有問題函卒。
至此,cvue-cli v2.0搭建完畢!
搭建cvue-cli v3.0
在cvue-cli v3.0中报嵌,我們需要將打包后的文件js和css該分離的分離,該壓縮的壓縮熊榛!
1.分離css樣式
安裝mini-css-extract-plugin插件
npm install --save-dev mini-css-extract-plugin
然后在webpack.base.config.js中引入插件锚国,并進行配置
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// 將vue-style-loader替換為 MiniCssExtractPlugin.loader
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
}
new MiniCssExtractPlugin({
// 配置分離樣式文件名,還有publicPath屬性可根據(jù)需要進行配置
filename: 'css/[name].css'
})
運行npm run build玄坦,可查看分離出的css文件
2.使用ejs將html模板化
安裝ejs-loader
npm install --save-dev ejs-loader
修改webpack.base.config.js血筑,支持ejs
// 添加loader規(guī)則
{
test: /\.ejs$/,
use: ['ejs-loader']
}
// 修改插件配置
new HtmlWebpackPlugins({
filename: 'index.html', // 輸出的html文件名,默認index.html
template: './public/index.ejs', // html模板路徑煎楣,注意這里也是./而不是../
chunks: ['main'] // 指定在html自動引入的js打包文件
})
- 下面設(shè)置下文件緩存
在輸出chunk時豺总,我們可以通過hash來設(shè)置文件名。webpack提供了三種hash方式择懂,分別是hash喻喳,chunkhash,contenthash困曙。
- hasn
hash是項目工程級的表伦,整個工程構(gòu)建的文件hash都是一樣的,所以只要工程文件有一個修改了慷丽,那么所有打包文件的hash都會改變蹦哼,這明顯不利于文件緩存,比如第三方庫的chunk要糊。 - chunkhash
chunkhash和hash不一樣纲熏,它根據(jù)不同的入口文件(Entry)進行依賴文件解析、構(gòu)建對應(yīng)的chunk锄俄,生成對應(yīng)的hash值局劲。我們在生產(chǎn)環(huán)境里把一些公共庫和程序入口文件區(qū)分開,單獨打包構(gòu)建珊膜,接著我們采用chunkhash的方式生成hash值容握,那么只要我們不改動公共庫的代碼,就可以保證其hash值不會受影響车柠。 - contenthash
contenthash表示由文件內(nèi)容產(chǎn)生的hash值剔氏,內(nèi)容不同產(chǎn)生的contenthash值也不一樣。在項目中竹祷,通常做法是把項目中css都抽離出對應(yīng)的css文件來加以引用谈跛。
下面修改webpack.base.config.js
// 配置編譯文件輸出路徑
output: {
// 以原始文件名的輸出文件名
filename: 'js/[name].[chunkhash].js',
path: path.resolve(__dirname, '../dist')
}
// 配置編譯文件輸出路徑
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash].css'
})
修改HtmlWebpackPlugins插件的配置
// 設(shè)置html模板生成路徑
new HtmlWebpackPlugins({
filename: 'index.html', // 輸出的html文件名,默認index.html
template: './public/index.ejs', // html模板路徑塑陵,注意這里也是./而不是../
chunks: ['main', 'vendor'], // 指定在html自動引入的js打包文件
})
然后大家可以分別試一下感憾,加上chunkhash和contenthash有什么區(qū)別,是不是和上面介紹的那樣令花。
最后運行npm run buil打包阻桅,打開index.html凉倚,看頁面是否顯示正常。
-
熱更新(HMR)不能和[chunkhash]同時使用
按照上面的步驟嫂沉,在運行打包文件時稽寒,頁面在時可以正常顯示的。但是如果運行了npm run dev趟章,就會報如下錯誤:
這是因為熱更新(HMR)不能和[chunkhash]同時使用杏糙。那么怎么辦呢?好說蚓土,我們不是把配置分為了本地環(huán)境和生產(chǎn)環(huán)境嗎宏侍?那么我們就在使用本地環(huán)境時不使用hash方式命名就可以啦!
修改webpack.dev.config.js 文件
const merge = require('webpack-merge')
const baseConfig = require('./webpack.base.config')
const path = require('path')
module.exports = merge(baseConfig, {
// 配置編譯文件輸出路徑
output: {
// 以原始文件名的輸出文件名
filename: 'js/[name].js',
path: path.resolve(__dirname, '../dist')
},
devServer: {
contentBase: './dist', //指定需要提供給本地服務(wù)的內(nèi)容的路徑蜀漆,默認加載index.html文件谅河,可根據(jù)需要修改
port: 8080, // 端口設(shè)置,默認8080
hot: true // 開啟熱更新嗜愈,瀏覽器自動刷新
}
})
- 將項目的引入的圖片等文件進行分離
修改webpack.base.config.js
// 圖片文件處理
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: {
loader: 'url-loader',
options: {
limit: 0, // 這設(shè)為0旧蛾,因為如果文件大小小于limit設(shè)置的值,會直接轉(zhuǎn)為base64
outputPath: 'images'
}
}
}
運行 npm run build蠕嫁,在打包后的項目目錄結(jié)構(gòu)中會多出一個images文件夾锨天。其他文件的分離方式也類似,如果需要可以自行配置剃毒。
結(jié)語
按照上面方式病袄,就可以搭建出一個基本的仿vue-cli的腳手架。建議大家還是親自去試一試赘阀,這樣可以加深理解益缠。
最后在附上本項目的git地址,大家可以下來看看:
cvue-cli的git地址
好啦基公,本篇文章內(nèi)容到此結(jié)束幅慌,如果對上面的內(nèi)容有什么不同的理解或是發(fā)現(xiàn)了錯誤,歡迎大家來交流指正轰豆。
感謝收看胰伍! \o(^o^)o