1.下載vue-cli
- npm install vue-cli -g
vue-cli的使用與詳細介紹,可以到github上獲取https://github.com/vuejs/vue-cli
2.安裝webpack項目模版
- vue init <template-name> <project-name>
- vue init webpack my-project
- npm install
安裝所有的依賴包,可以得到如下的目錄結構
3.目錄結構與文件配置說明
首先對目錄結構進行說明,
1.build目錄,主要利用webpack與node插件啟動一些相關服務的js文件
2.config目錄主要是針對開發環境,生產環境,測試環境的配置信息
3.src是我們自己開發時的源碼目錄(可指定修改名稱)
4.static是一些第三方庫的包用到的靜態資源目錄(可指定修改名稱)
說明每個文件:
主要入口文件,dev-server.js文件,幾乎每一句話都進行了注釋,有些地方,涉及了其他關聯文件,下面也會有相應的注釋的方式
- // 引入檢查版本js模塊
- require('./check-versions')()
- // 引入配置文件信息模塊
- var config = require('../config')
- // 判斷開發環境
- if (!process.env.NODE_ENV) process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
- // 引入nodejs的path模塊,進行一些路徑的操作,詳情可以查看node官方的api
- var path = require('path')
- // 引入nodejs的一個框架express,可以幫助我們快速搭建一個node服務 github https://github.com/expressjs/express
- var express = require('express')
- // 引入node為webpack提供的一個模塊服務 github https://github.com/webpack/webpack
- var webpack = require('webpack')
- // 可以指定打開指定的url使用指定的瀏覽器或者應用,詳情可以去看一下github https://github.com/sindresorhus/opn
- var opn = require('opn')
- // 一個可以設置幫助我們進行服務器轉發代理的中間件 https://github.com/chimurai/http-proxy-middleware
- var proxyMiddleware = require('http-proxy-middleware')
- // 根據當前啟動環境選擇加載相應的配置文件,webpack.prod.conf與webpack.dev.conf文件的說明后面也有
- var webpackConfig = process.env.NODE_ENV === 'testing'
- ? require('./webpack.prod.conf')
- : require('./webpack.dev.conf')
- // 端口號的設置
- var port = process.env.PORT || config.dev.port
- // 獲取需要代理的服務api
- // https://github.com/chimurai/http-proxy-middleware
- var proxyTable = config.dev.proxyTable
- // 啟動一個express服務
- var app = express()
- // 加載webpack配置
- var compiler = webpack(webpackConfig)
- // webpack的開發中間件,專門為webpack提供的一個簡單的中間件,可以讓文件都加載內存中,不去讀寫硬盤,並且當文件被改動的時候,不會刷新頁面就會部署成功
- var devMiddleware = require('webpack-dev-middleware')(compiler, {
- publicPath: webpackConfig.output.publicPath,
- quiet: true
- })
- // 一個為webpack提供的熱部署中間件。https://github.com/glenjamin/webpack-hot-middleware
- var hotMiddleware = require('webpack-hot-middleware')(compiler, {
- log: () => {}
- })
- // 當html被改變的時候,讓html被強制部署,使用這個中間件html-webpack-plugin,https://github.com/ampedandwired/html-webpack-plugin
- compiler.plugin('compilation', function (compilation) {
- compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
- hotMiddleware.publish({ action: 'reload' })
- cb()
- })
- })
- // 遍歷代理的配置信息,並且使用中間件加載進去
- Object.keys(proxyTable).forEach(function (context) {
- var options = proxyTable[context]
- if (typeof options === 'string') {
- options = { target: options }
- }
- app.use(proxyMiddleware(context, options))
- })
- // 當訪問找不到的頁面的時候,該中間件指定了一個默認的頁面返回https://github.com/bripkens/connect-history-api-fallback
- app.use(require('connect-history-api-fallback')())
- // 使用中間件
- app.use(devMiddleware)
- // 熱部署
- app.use(hotMiddleware)
- // 根據配置信息拼接一個目錄路徑,然后將該路徑下的文件交給express的靜態目錄管理
- var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
- app.use(staticPath, express.static('./static'))
- var uri = 'http://localhost:' + port
- devMiddleware.waitUntilValid(function () {
- console.log('> Listening at ' + uri + '\n')
- })
- // 導出的對象
- module.exports = app.listen(port, function (err) {
- if (err) {
- console.log(err)
- return
- }
- // when env is testing, don't need open it
- if (process.env.NODE_ENV !== 'testing') {
- opn(uri)
- }
- })
- var path = require('path')
- var config = require('../config')
- // 工具類,下面會用到
- var utils = require('./utils')
- // 工程目錄,就是當前目錄build的上一層目錄
- var projectRoot = path.resolve(__dirname, '../')
- var env = process.env.NODE_ENV
- // 是否在開發環境中使用cssSourceMap,默認是false,該配置信息在config目錄下的index.js中可以查看
- var cssSourceMapDev = (env === 'development' && config.dev.cssSourceMap)
- var cssSourceMapProd = (env === 'production' && config.build.productionSourceMap)
- var useCssSourceMap = cssSourceMapDev || cssSourceMapProd
- // 導出的對象,就是webpack的配置項,詳情可以參考的webpack的配置說明,這里會將出現的都一一說明一下
- module.exports = {
- // 指明入口函數
- entry: {
- app: './src/main.js'
- },
- // 輸出配置項
- output: {
- // 路徑,從config/index讀取的,值為:工程目錄下的dist目錄,需要的自定義的也可以去修改
- path: config.build.assetsRoot,
- // 發布路徑,這里是的值為/,正式生產環境可能是服務器上的一個路徑,也可以自定義
- publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
- filename: '[name].js'
- },
- // 配置模塊如何被解析,就是import或者require的一些配置
- resolve: {
- // 當使用require或者import的時候,自動補全下面的擴展名文件的擴展名,也就是說引入的時候不需要使用擴展名
- extensions: ['', '.js', '.vue', '.json'],
- // 當我們require的東西找不到的時候,可以去node_modules里面去找,
- fallback: [path.join(__dirname, '../node_modules')],
- // 別名,在我們require的時候,可以使用這些別名,來縮短我們需要的路徑的長度
- alias: {
- 'vue$': 'vue/dist/vue.common.js',
- 'src': path.resolve(__dirname, '../src'),
- 'assets': path.resolve(__dirname, '../src/assets'),
- 'components': path.resolve(__dirname, '../src/components')
- }
- },
- // 同上
- resolveLoader: {
- fallback: [path.join(__dirname, '../node_modules')]
- },
- // 對相應文件的編譯使用什么工具的配置
- module: {
- // loader之前的配置,會對.vue,.js的文件用eslint進行編譯,include是包含的文件,exclude是排除的文件,可以使用的正則
- preLoaders: [
- {
- test: /\.vue$/,
- loader: 'eslint',
- include: [
- path.join(projectRoot, 'src')
- ],
- exclude: /node_modules/
- },
- {
- test: /\.js$/,
- loader: 'eslint',
- include: [
- path.join(projectRoot, 'src')
- ],
- exclude: /node_modules/
- }
- ],
- // 這里也是相應的配置,test就是匹配文件,loader是加載器,
- // query比較特殊,當大小超過10kb的時候,會單獨生成一個文件,文件名的生成規則是utils提供的方法,當小於10kb的時候,就會生成一個base64串放入js文件中
- loaders: [
- {
- test: /\.vue$/,
- loader: 'vue'
- },
- {
- test: /\.js$/,
- loader: 'babel',
- include: [
- path.join(projectRoot, 'src')
- ],
- exclude: /node_modules/
- },
- {
- test: /\.json$/,
- loader: 'json'
- },
- {
- test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
- loader: 'url',
- query: {
- limit: 10000,
- name: utils.assetsPath('img/[name].[hash:7].[ext]')
- }
- },
- {
- test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
- loader: 'url',
- query: {
- limit: 10000,
- name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
- }
- }
- ]
- },
- // eslint的配置
- eslint: {
- formatter: require('eslint-friendly-formatter')
- },
- // vue-loader的配置
- vue: {
- loaders: utils.cssLoaders({ sourceMap: useCssSourceMap }),
- postcss: [
- require('autoprefixer')({
- browsers: ['last 2 versions']
- })
- ]
- }
- }
webpack.dev.comf.js
- var config = require('../config')
- var webpack = require('webpack')
- // https://github.com/survivejs/webpack-merge 提供一個合並生成新對象函數
- var merge = require('webpack-merge')
- var utils = require('./utils')
- var baseWebpackConfig = require('./webpack.base.conf')
- var HtmlWebpackPlugin = require('html-webpack-plugin')
- var FriendlyErrors = require('friendly-errors-webpack-plugin')
- // 在瀏覽器不刷新的情況下,也可以看到改變的效果,如果刷新失敗了,他就會自動刷新頁面
- Object.keys(baseWebpackConfig.entry).forEach(function (name) {
- baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
- })
- module.exports = merge(baseWebpackConfig, {
- module: {
- // 后面會有對utils的解釋,這里是對單獨的css文件,用相應的css加載器來解析
- loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
- },
- // 在開發模式下,可以在webpack下面找到js文件,在f12的時候,
- devtool: '#eval-source-map',
- // 將webpack的插件放入
- plugins: [
- // 通過插件修改定義的變量
- new webpack.DefinePlugin({
- 'process.env': config.dev.env
- }),
- // webpack優化的這個一個模塊,https://github.com/glenjamin/webpack-hot-middleware#installation--usage
- new webpack.optimize.OccurrenceOrderPlugin(),
- // 熱加載
- new webpack.HotModuleReplacementPlugin(),
- // 當編譯出現錯誤的時候,會跳過這部分代碼
- new webpack.NoErrorsPlugin(),
- // filename生成的文件名,template是模版用的文件名,https://github.com/ampedandwired/html-webpack-plugin
- new HtmlWebpackPlugin({
- filename: 'index.html',
- template: 'index.html',
- // 讓打包生成的html文件中css和js就默認添加到html里面,css就添加到head里面,js就添加到body里面
- inject: true
- }),
- new FriendlyErrors()
- ]
- })
utils.js和config目錄下面的js文件都比較好辨認是干什么的,config下面都是配置信息,json對象,很好理解,utils下面就是導出了幾個常用的方法,主要也就是用在了上述的幾個js文件里面,另外關於生產階段和測試階段的js說明,后面會有文章說明
補充:
項目中配置的config/index.js,有dev和production兩種環境的配置 以下介紹的是production環境下的webpack配置的理解
1 var path = require('path')
2
3 module.exports = {
4 build: { // production 環境
5 env: require('./prod.env'), // 使用 config/prod.env.js 中定義的編譯環境
6 index: path.resolve(__dirname, '../dist/index.html'), // 編譯輸入的 index.html 文件
7 assetsRoot: path.resolve(__dirname, '../dist'), // 編譯輸出的靜態資源路徑
8 assetsSubDirectory: 'static', // 編譯輸出的二級目錄
9 assetsPublicPath: '/', // 編譯發布的根目錄,可配置為資源服務器域名或 CDN 域名
10 productionSourceMap: true, // 是否開啟 cssSourceMap
11 // Gzip off by default as many popular static hosts such as
12 // Surge or Netlify already gzip all static assets for you.
13 // Before setting to `true`, make sure to:
14 // npm install --save-dev compression-webpack-plugin
15 productionGzip: false, // 是否開啟 gzip
16 productionGzipExtensions: ['js', 'css'] // 需要使用 gzip 壓縮的文件擴展名
17 },
18 dev: { // dev 環境
19 env: require('./dev.env'), // 使用 config/dev.env.js 中定義的編譯環境
20 port: 8080, // 運行測試頁面的端口
21 assetsSubDirectory: 'static', // 編譯輸出的二級目錄
22 assetsPublicPath: '/', // 編譯發布的根目錄,可配置為資源服務器域名或 CDN 域名
23 proxyTable: {}, // 需要 proxyTable 代理的接口(可跨域)
24 // CSS Sourcemaps off by default because relative paths are "buggy"
25 // with this option, according to the CSS-Loader README
26 // (https://github.com/webpack/css-loader#sourcemaps)
27 // In our experience, they generally work as expected,
28 // just be aware of this issue when enabling this option.
29 cssSourceMap: false // 是否開啟 cssSourceMap
30 }
31 }

