從零搭建webpack4 + vue + vue-rout + vuex項目架構(gòu)

配置前說明:確保已安裝node環(huán)境藕帜。

檢查是否安裝node環(huán)境:

  1、終端輸入node -v或node --version
  2、終端輸入npm -v或npm --version

一、配置前命令簡寫說明:

1衬以、npm inpm install區(qū)別:
a)npm i是npm install縮寫缓艳。
b)用npm i安裝的模塊無法用npm uninstall刪除,用npm uninstall i才卸載掉看峻。
c)npm i會幫助檢測與當前node版本最匹配的npm包版本號阶淘,并匹配出來相互依賴的npm包應(yīng)該提升的版本號。
d)部分npm包在當前node版本下無法使用互妓,必須使用建議版本溪窒。
e)安裝報錯時intall肯定會出現(xiàn)npm-debug.log 文件,npm i不一定车猬。
2霉猛、npm -Dnpm -S的區(qū)別:
a)-S就是--save的簡寫尺锚。
b)-D就是--save-dev 這樣安裝的包的名稱及版本號就會存在package.json的devDependencies這個里面珠闰,而--save會將包的名稱及版本號放在dependencies里面。

二瘫辩、webpack基礎(chǔ)配置(開發(fā)環(huán)境):

命令運行前提:終端進入項目目錄文件夾里伏嗜,以下不再說明。
1伐厌、創(chuàng)建一個項目目錄demo承绸,使用NPM初始化配置:
npm init
執(zhí)行后,會有一系列選項挣轨,可以按回車快速確認军熏,完成后,會在demo目錄生成一個package.json文件卷扮。
2荡澎、使用NPM安裝webpack模塊、webpack-dev-server模塊和webpack-cli模塊:
npm install webpack --save-dev
npm install webpack-dev-server --save-dev
npm i -D webpack-cli
安裝成功后晤锹,在package.json中會多幾項配置:

"devDependencies": {
    "webpack": "^4.29.6",
    "webpack-cli": "^3.2.3",
    "webpack-dev-server": "^3.2.1"
  }

3摩幔、在demo目錄下創(chuàng)建webpack.config.js并初始化內(nèi)容:

const config = {

};
module.exports = config;

4、在package.jsonscripts里增加一個快速啟動webpack-dev-server服務(wù)的腳本和打包腳本:

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

其中--config是指向webpack-dev-server讀取的配置文件路徑鞭铆。
--open會執(zhí)行命令時自動在瀏覽器打開頁面或衡,默認地址是127.0.0.1:8080
IP和端口都是可以配置的车遂,例如:

//...
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --host 172.172.172.1 --port 8888 --open --config=webpack.config.js"
  },
  //...

這樣訪問地址就改為了172.172.172.1:8888封断。
5、入口(Entry)出口(Output)

webpack配置中最重要也是必選的兩項是入口(Entry)和出口(Output)舶担。
入口的作用是告訴webpack從哪里開始尋找依賴澄港,并且編譯。
出口的作用是用來配置編譯后的文件存儲位置和文件名柄沮。

在demo目錄下新建一個空的main.js作為入口的文件回梧,然后在webpack.config.js中進行入口和出口的配置:

const path = require('path');

const config = {
  entry: {
    main: './main'
  },
  output: {
    path: path.join(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'main.js'
  }
};

entry中的main就是配置的單入口废岂,webpack會從main.js文件開始工作。
output中path選項用來存放打包后文件的輸出目錄狱意,是必填項湖苞。
publicPath指定資源文件引用的目錄,如果你的資源存放在CDN上详囤,這里可以填CDN的網(wǎng)址财骨。
filename用于指定輸出文件的名稱。
因此藏姐,這里配置的output意為打包后的文件會存儲為demo/dist/main.js隆箩,只要在html中引入即可。

在demo目錄下新建一個index.html作為項目的入口:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1 user-scalable=0">
    <title>Demo</title>
</head>
<body>
    <div id="app"></div>
    <script src="./dist/main.js"></script>
</body>
</html>

運行npm run build命令羔杨,后再執(zhí)行npm run dev即可啟動了一個空項目捌臊。
6、webpack加載器(Loaders):
webpack通過安裝不同的加載器(Loaders)可以對各種后綴名的文件進行處理兜材。
css-loaderstyle-loader理澎,通過NPM安裝:
npm install css-loader --save-dev
npm install style-loader --save-dev
安裝完成后,在webpack.config.js文件里配置Loader曙寡,增加對.css文件的處理:

const path = require('path');

const config = {
  //...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'css-loader',
          'style-loader'
        ]
      }
    ]
  }
};
module.exports = config;

在module對象的rules屬性中可以指定一系列的loaders糠爬,每一個loader都必須包含testuse兩個選項。這段配置的意思是說举庶,當webpack編譯過程中遇到require()import語句導(dǎo)入一個后綴名為.css的文件時执隧,先將它通過css-loader轉(zhuǎn)換,然后繼續(xù)打包户侥。
use選項的值可以是數(shù)組或字符串镀琉,如果是數(shù)組,它的編譯順序就是從后往前添祸。

在demo目錄下新建一個style.css的文件滚粟,作為全局css樣式,并在main.js中導(dǎo)入:

//main.js
import './style.css';

7刃泌、webpack插件(Plugins):
通過NPM安裝extract-text-webpack-plugin插件:
npm install extract-text-webpack-plugin@next --save-dev
然后在webpack.config.js配置文件中導(dǎo)入插件凡壤,并改寫loader的配置和index.html:

const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const config = {
    //...
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    { loader: "style-loader" },
                    { loader: "css-loader" }
                ]
            }
        ]
    },
    plugins: [
        // 重命名提取后的css文件
        new ExtractTextPlugin('main.css')
    ]
};

module.exports = config;
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1 user-scalable=0">
    <title>Demo</title>
    <link rel="stylesheet" href="./dist/main.css">
</head>
...

到此,基本的webpack配置就寫完了耙替。webpack雖然看似復(fù)雜亚侠,但它只不過是一個js配置文件,只要搞清楚入口(Entry)俗扇、出口(Output)硝烂、加載器(Loaders)插件(Plugins)這四個概念,使用起來就不那么困惑了铜幽。

三滞谢、單文件組件和vue-loader:

一個.vue文件一般包含3部分串稀,即<template><script><style>狮杨,如下所示:

//component.vue
<template>
  <div>
    <span>你好:{{ name }}</span>
  </div>
</template>
<script>
  export default {
    props: {
      name: {
        type: String,
        default: ''
      }
    }
  }
</script>
<style scoped>
  span {
    color: #f60;
  }
</style>

在component.vue文件中母截,<template></template>之間的代碼就是該組件的模板HTML,<style></style>之間的是css樣式橄教,示例中的<style>標簽使用了scoped屬性清寇,表示當前的css只在這個組件有效,如果不加护蝶,那么span的樣式會應(yīng)用到整個項目华烟。

使用.vue文件需要先安裝vue-loader、vue-style-loader等加載器并做配置持灰。因為要使用ES6語法盔夜,還需要安裝babel和babel-loader等加載器。使用NPM逐個安裝以下依賴:
npm install --save vue
npm install --save-dev vue-loader
npm install --save-dev vue-style-loader
npm install --save-dev vue-template-compiler
npm install --save-dev vue-hot-reload-api
npm install --save-dev babel
npm i babel-loader@7.1.5 -D
npm install --save-dev babel-core
npm install --save-dev babel-plugin-transform-runtime
npm install --save-dev babel-preset-es2015
npm install --save-dev babel-runtime
安裝完成后搅方,修改配置文件webpack.config.js來支持對.vue文件及ES6的解析:

// webpack.config.js
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');

const config = {
    entry: {
        main: './main'
    },
    output: {
        path: path.join(__dirname, './dist'),
        publicPath: '/dist/',
        filename: 'main.js'
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        css: ExtractTextPlugin.extract({
                            use: 'css-loader',
                            fallback: 'vue-style-loader'
                        })
                    }
                }
            },
            {
                test: /\.js$/,
                use: [
                    {
                        loader: 'babel-loader'
                    }
                ],
                exclude: /node_module/
            },
            {
                test: /\.css$/,
                use: [
                    { loader: "style-loader" },
                    { loader: "css-loader" }
                ]
            }
        ]
    },
    plugins: [
        // 重命名提取后的css文件
        new ExtractTextPlugin('main.css'),
        new VueLoaderPlugin()
    ]
};

module.exports = config;

vue-loader在編譯.vue文件時比吭,會對<template>绽族、<script>姨涡、<style>分別處理,所以在vue-loader選項里多了一項options來進一步對不同語言進行配置吧慢。比如在對css進行處理時涛漂,會先通過css-loader解析,然后把處理結(jié)果再交給vue-style-loader處理检诗。

在demo目錄下新建一個名為.babelrc的文件匈仗,并寫入babel的配置,webpack會依賴此配置文件來使用babel編譯ES6代碼:

{
    "presets": ["es2015"],
    "plugins": ["transform-runtime"],
    "comments": false
}

配置好后逢慌,就可以使用.vue文件了悠轩。每個.vue文件就代表一個組件,組件之間可以相互依賴攻泼。

四火架、webpack用于生產(chǎn)環(huán)境:

1、先對webpack進一步配置忙菠,來支持更多常用的功能:
通過NPM安裝url-loaderfile-loader來支持圖片何鸡、字體等文件:
npm install --save-dev url-loader
npm install --save-dev file-loader

// webpack.config.js
const config = {
  //...
  module: {
    rules: [
      //...
      {
        test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
        loader: 'url-loader?limit=1024'
      }
    ]
  }
};

當遇到.gif.png牛欢、.ttf等格式文件時骡男,url-loader會把它們一起編譯到dist目錄下,"?limit=1024"是指如果這個文件小于1kb就以base64的形式加載傍睹,不會生成一個文件隔盛。
webpack.config.jsoutput選項里已經(jīng)指定了pathpubilcPath犹菱,打完包后,所有的資源都會保存在demo/dist目錄下吮炕。
2已亥、為了方便開發(fā)和生產(chǎn)環(huán)境的切換,在demo目錄下再新建一個用于生產(chǎn)環(huán)境的配置文件webpack.prod.config.js来屠。
打包會用到下面兩個依賴虑椎,使用NPM安裝:
npm install --save-dev webpack-merge
npm install --save-dev html-webpack-plugin
package.json中,再加入一個probuild的快捷腳本用來打包:

{
  //...
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --open --config=webpack.config.js",
    "build": "webpack --progress --hide-modules",
    "probuild": "webpack --mode production --progress --hide-modules --config=webpack.prod.config.js"
  },
  //...
}

webpack.prod.config.js代碼如下:

// webpack.prod.config.js
const webpack = require('webpack');
const HtmlwebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const merge = require('webpack-merge');
const webpackBaseConfig = require('./webpack.config.js');
const VueLoaderPlugin = require('vue-loader/lib/plugin');

// 清空基本配置的插件列表
webpackBaseConfig.plugins = [];

module.exports = merge(webpackBaseConfig, {
    output: {
        publicPath: '/dist/',
        // 將入口文件重命名為帶有20位hash值得唯一文件
        filename: '[name].[hash].js'
    },
    // 定義當前為生產(chǎn)環(huán)境
    mode: 'production',
    plugins: [
        new ExtractTextPlugin({
            filename: '[name].[hash].css',
            allChunks: true
        }),
        // 提取模板俱笛,并保留入口html文件
        new HtmlwebpackPlugin({
            filename: './index_prod.html',
            template: './index.html',
            minify: {
                //對 html 文件進行壓縮捆姜,minify 的屬性值是一個壓縮選項或者 false 。默認值為false, 不對生成的 html 文件進行壓縮
                removeComments:true, // 去除注釋
                collapseWhitespace: true //是否去除空格
            }
        }),
        new VueLoaderPlugin()
    ],
    // 對js文件進行壓縮
    optimization: {
        splitChunks: {
            chunks: 'all'
        },
        runtimeChunk: true
    }
})

上面安裝的webpack-merge模塊就是用于合并兩個webpack的配置文件迎膜,所以prod的配置是在webpack.config.js基礎(chǔ)上擴展的泥技。
html-webpack-plugin是用來生成html文件的,它通過template選項來讀取指定的模板index.html磕仅,然后輸入到filename指定的目錄珊豹,就是demo/index_prod.html

五榕订、vue-router配置:

1店茶、在demo目錄下新建一個app.vue文件并寫入以下內(nèi)容:

<!-- app.vue -->
<template>
    <div>
        <router-view></router-view>
    </div>
</template>
<script>
    export default {
        name: 'app'
    }
</script>

app.vue里的路由視圖<router-view>掛載所有的路由組件。
運行網(wǎng)頁時劫恒,<router-view>會根據(jù)當前路由動態(tài)渲染不同的頁面組件贩幻。路由切換時,切換的是<router-view>掛載的組件两嘴,其他的內(nèi)容并不會變化丛楚。
2、通過NPM安裝vue-router:
npm install --save vue-router
main.js里使用Vue.use()加載插件:

import './style.css';
//導(dǎo)入Vue框架
import Vue from 'vue';
//導(dǎo)入vue-router路由
import VueRouter from 'vue-router';
//導(dǎo)入app.vue組件
import App from './app.vue';

Vue.use(VueRouter);

//創(chuàng)建Vue根實例
new Vue({
  el: '#app',
  render: h => h(App)
});

每個頁面對應(yīng)一個組件憔辫,也就是對應(yīng)一個.vue文件趣些。
3、在demo目錄下創(chuàng)建views文件夾贰您,用于存放所有的頁面坏平,然后在views創(chuàng)建index.vue文件并寫入以下內(nèi)容:

<!-- index.vue -->
<template>
    <div>
        <h1>首頁</h1>
    </div>
</template>
<script>
    export default {
        name: 'index'
    }
</script>

4、再回到main.js枉圃,完成路由的剩余配置功茴。創(chuàng)建一個數(shù)組來制定路由匹配列表,每一個路由映射一個組件:

//main.js
const Routers = [
    {
        path: '/index',
        component: (resolve) => require(['./views/index.vue'], resolve)
    },
    // 當訪問路徑不存在時孽亲,重定向到首頁
    {
        path: '*',
        redirect: '/index'
    }
]

Routers里每一項的path屬性就是指定當前匹配的路徑坎穿,component是映射的組件。上例的寫法,webpack會把每一個路由都打包為一個js文件玲昧,在請求到該頁面時栖茉,才去加載這個頁面的js,也就是異步實現(xiàn)的懶加載(按需加載)孵延。這樣做的好處是不需要在打開首頁的時候就把所有的頁面內(nèi)容全部加載進來吕漂,只在訪問時才加載。
5尘应、使用了異步路由后惶凝,編譯出的每個頁面的js都叫做chunk(塊),它們命名默認是0.main.js犬钢、1.main.js......可以在webpack配置的出口output里通過設(shè)置chunkFilename字段修改chunk命名苍鲜,例如:

//webpack.config.js
output: {
        path: path.join(__dirname, './dist'),
        publicPath: '/dist/',
        filename: '[name].js',
        chunkFilename: '[name].chunk.js'
    },

有了chunk后,在每個頁面(.vue文件)里寫的樣式也需要配置后才會打包進main.css玷犹,配置插件:

//webpack.config.js
plugins: [
        // 重命名提取后的css文件
        new ExtractTextPlugin({
            filename: '[name].css',
            allChunks: true
        }),
        new VueLoaderPlugin()
    ]

6混滔、繼續(xù)在main.js里完成配置和路由實例:

//main.js
const RouterConfig = {
    // 使用HTML5的History路由模式
    mode: 'history',
    routes: Routers
};
const router = new VueRouter(RouterConfig);

//創(chuàng)建Vue根實例
new Vue({
    el: '#app',
    router: router,
    render: h => h(App)
});

RouterConfig里,設(shè)置modehistory會開啟HTML5History路由模式歹颓,通過“/”設(shè)置路徑坯屿。如果不配置mode,就會使用“#”來設(shè)置路徑巍扛。開啟History路由领跛,在生產(chǎn)環(huán)境時服務(wù)端必須進行配置,將所有路由都指向同一個html或設(shè)置404頁面為該html电湘,否則刷新時頁面會出現(xiàn)404隔节。
7鹅经、webpack-dev-server也要配置下來支持History路由寂呛,在package.json中修改dev命令:

"scripts": {
    //...
    "dev": "webpack-dev-server --open --history-api-fallback --config=webpack.config.js",
    //...
  },

增加了--history-api-fallback,所有的路由都會指向index.html瘾晃。

六贷痪、vuex配置:

1、通過NPM安裝Vuex:
npm install --save vuex
它的用法與vue-router類似蹦误,在main.js里劫拢,通過Vue.use()使用Vuex:

// main.js
import './style.css';
//導(dǎo)入Vue框架
import Vue from 'vue';
//導(dǎo)入vue-router路由
import VueRouter from 'vue-router';
//導(dǎo)入Vuex
import Vuex from 'vuex';
//導(dǎo)入app.vue組件
import App from './app.vue';

Vue.use(VueRouter);
Vue.use(Vuex);

//路由配置
//省略...

const store = new Vuex.Store({
    // vuex的配置
});

//創(chuàng)建Vue根實例
new Vue({
    el: '#app',
    router: router,
    // 使用vuex
    store: store,
    render: h => h(App)
});

倉庫store包含了應(yīng)用的數(shù)據(jù)(狀態(tài))和操作過程。Vuex里的數(shù)據(jù)都是響應(yīng)式的强胰,任何組件使用同一store的數(shù)據(jù)時舱沧,只要store的數(shù)據(jù)變化,對應(yīng)的組件也會立即更新偶洋。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末熟吏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌牵寺,老刑警劉巖悍引,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異帽氓,居然都是意外死亡趣斤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門黎休,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浓领,“玉大人,你說我怎么就攤上這事势腮∧魇牛” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵嫉鲸,是天一觀的道長撑蒜。 經(jīng)常有香客問我,道長玄渗,這世上最難降的妖魔是什么座菠? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮藤树,結(jié)果婚禮上浴滴,老公的妹妹穿的比我還像新娘。我一直安慰自己岁钓,他們只是感情好升略,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著屡限,像睡著了一般品嚣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钧大,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天翰撑,我揣著相機與錄音,去河邊找鬼啊央。 笑死眶诈,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的瓜饥。 我是一名探鬼主播逝撬,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼乓土!你這毒婦竟也來了宪潮?” 一聲冷哼從身側(cè)響起靠闭,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎坎炼,沒想到半個月后愧膀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡谣光,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年檩淋,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萄金。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡蟀悦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出氧敢,到底是詐尸還是另有隱情日戈,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布孙乖,位于F島的核電站浙炼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏唯袄。R本人自食惡果不足惜弯屈,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望恋拷。 院中可真熱鬧资厉,春花似錦、人聲如沸蔬顾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诀豁。三九已至窄刘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間且叁,已是汗流浹背都哭。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留逞带,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓纱新,卻偏偏與公主長得像展氓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子脸爱,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

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