從0搭建基于Webpack4的Vue前端腳手架

前言

今天的內(nèi)容是如何從零搭建基于Webpack4的Vue前端腳手架碾篡,如有問題虱而,歡迎來交流啊开泽!
整個過程大致分為以下幾個步驟:

  1. 搭建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)如下:


初始目錄結(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"
}
  1. 配置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打包文件
        })

    ]
}

  1. 修改main.js文件
document.write('hello cvue-cli樟遣!')
  1. 運行npm run build打包編譯文件而叼,打包完的目錄結(jié)構(gòu)如下
打包完的文件

瀏覽器打開index.html文件,頁面中出現(xiàn) “hello cvue-cli豹悬!”葵陵,恭喜你成功地邁出了第一步,下面再接再厲瞻佛!

  1. 下面搭建開發(fā)環(huán)境的熱監(jiān)測服務(wù)器
npm install --save-dev webpack-dev-server
  1. 修改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 // 開啟熱更新绊困,瀏覽器自動刷新
}
  1. 將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

  1. 首先安裝相關(guān)依賴包(每個具體的作用就不介紹了怨酝,可自行百度)
npm install --save vue
npm install --save-dev vue-loader vue-template-compiler vue-style-loader css-loader
  1. 修改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()
]
  1. 添加App.vue文件


    App.vue
<template>
  <div id="app"></div>
</template>

<script>
export default {
  data() {
    return {
      message: 'hello cvue-cli'
    }
  }
}
</script>

<style>
#app {
  color: red;
}
</style>

  1. 下面修改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

  1. 修改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單文件起作用了料身!

  1. 下面安裝file-loader和url-loader
// 因為url-loader基于file-loader,所以都要安裝衩茸。
// url-loader在file-loader上進行擴展芹血,當文件小于多少KB時進行base64轉(zhuǎn)換
npm install --save-dev file-loader url-loader
  1. 在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
          }
     }
}
  1. 在src目錄下創(chuàng)建assets文件夾,用來存放我們的圖片(這里使用vue官方logo)楞慈,然后修改App.vue文件


    assets文件夾
<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ù)完善。


初級版cvue-cli v2.0
  1. 下面安裝和使用vue-router

安裝vue-router

npm install --save vue-router

添加相關(guān)文件蝎宇,項目結(jié)構(gòu)如下


添加使用vue-router相關(guān)文件

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)下圖:


成功使用vue-router
  1. 安裝使用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文件


添加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,效果如下


less生效的效果圖

下面我們在運行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文件


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打包文件
})
  1. 下面設(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凉倚,看頁面是否顯示正常。

  1. 熱更新(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 // 開啟熱更新嗜愈,瀏覽器自動刷新
  }
})
  1. 將項目的引入的圖片等文件進行分離
    修改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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市酸休,隨后出現(xiàn)的幾起案子骂租,更是在濱河造成了極大的恐慌,老刑警劉巖斑司,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渗饮,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機互站,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門私蕾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人云茸,你說我怎么就攤上這事是目。” “怎么了标捺?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長揉抵。 經(jīng)常有香客問我亡容,道長,這世上最難降的妖魔是什么冤今? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任闺兢,我火速辦了婚禮,結(jié)果婚禮上戏罢,老公的妹妹穿的比我還像新娘屋谭。我一直安慰自己,他們只是感情好龟糕,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布桐磁。 她就那樣靜靜地躺著,像睡著了一般讲岁。 火紅的嫁衣襯著肌膚如雪我擂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天缓艳,我揣著相機與錄音校摩,去河邊找鬼。 笑死阶淘,一個胖子當著我的面吹牛衙吩,可吹牛的內(nèi)容都是我干的关霸。 我是一名探鬼主播煌妈,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼门躯!你這毒婦竟也來了霉猛?” 一聲冷哼從身側(cè)響起尺锚,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎惜浅,沒想到半個月后瘫辩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年伐厌,在試婚紗的時候發(fā)現(xiàn)自己被綠了承绸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡挣轨,死狀恐怖军熏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卷扮,我是刑警寧澤荡澎,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站晤锹,受9級特大地震影響摩幔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鞭铆,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一或衡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧车遂,春花似錦封断、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至柄沮,卻和暖如春回梧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背祖搓。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工狱意, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拯欧。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓详囤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親镐作。 傳聞我的和親對象是個殘疾皇子藏姐,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容