首先須要下載node.js(推薦直接官網找最新的版本),下載完成後會自帶npm包管理工具,打開cmd命令行界面,輸入npm -v 、node -v檢查node.js與npm是否安裝成功。(安裝成功會顯示版本號)php
若是下載太慢的話能夠把npm換成國內淘寶鏡像cnpm:(我的推薦直接使用npm,以前有使用cnpm在下載一些模塊時出現版本對應不上)css
npm install -g cnpm --registry=https://registry.npm.taobao.org
新建文件夾,而後使用命令行進入文件夾中,命令行執行 npm init 初始化,輸入項目名、版本號、做者...最後OK,文件夾中會生成package.json文件html
文件夾中會包含一些基本信息(項目名、版本號...):vue
{ "name": "cs", "version": "1.0.1", "description": "cs", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
到如今項目文件中僅有一個文件package.json,其中定義了這個項目所須要的各類模塊,以及項目的配置信息(好比名稱、版本、許可證等元數據)。npm install
命令根據這個配置文件,自動下載所需的模塊,也就是配置項目所需的運行和開發環境。html5
npm install vue vue-loader webpack webpack-cli --save-dev
--save-dev 安裝的包,會被寫入到 devDependencies 對象裏面去;(簡寫 -D)
--save 安裝的包,則被寫入到 dependencies 對象裏面去。(簡寫 -S)
dependencies :應用可以正常運行所依賴的包。這種 dependencies 是最多見的,用戶在使用 npm install 安裝你的包時會自動安裝這些依賴。
devDependencies:開發應用時所依賴的工具包。一般是一些開發、測試、打包工具,例如 webpack、ESLint、Mocha。
應用正常運行並不依賴於這些包,用戶在使用 npm install 安裝你的包時也不會安裝這些依賴。
devDependencies 裏面的插件(好比各類loader,babel全家桶及各類webpack的插件等)只用於開發環境,不用於生產環境,所以不須要打包;而 dependencies 是須要發佈到生產環境的,是要打包的。
能夠經過命令行執行:❶ npm install vue vue-router -S; ❷ npm install webpack webpack-cli....(加載本身所須要的模塊) -D; 來進行加載模塊node
構建一個簡單的vue項目所須要用到的最基本的模塊: npm install vue vue-router -S npm install vue-loader webpack webpack-cli webpack-dev-server -D npm install css-loader style-loader -D npm install babel-core babel-loader babel-preset-env babel-preset-stage-2 babel-helper-vue-jsx-merge-props babel-plugin-syntax-jsx babel-plugin-transform-runtime babel-plugin-transform-vue-jsx -D
也能夠直接將如下模塊內容複製進package.json中,運行npm install加載模塊:webpack
"dependencies": { "vue": "^2.6.10", "vue-router": "^3.0.6" }, "devDependencies": { "autoprefixer": "^9.6.0", "axios": "^0.19.0", "babel-core": "^6.26.3", "babel-helper-vue-jsx-merge-props": "^2.0.3", "babel-loader": "^7.1.5", "babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-runtime": "^6.23.0", "babel-plugin-transform-vue-jsx": "^3.7.0", "babel-polyfill": "^6.26.0", "babel-preset-env": "^1.7.0", "babel-preset-stage-2": "^6.24.1", "copy-webpack-plugin": "^5.0.3", "cross-env": "^5.2.0", "css-loader": "^3.0.0", "file-loader": "^4.0.0", "generate-asset-webpack-plugin": "^0.3.0", "html-webpack-plugin": "^3.2.0", "lockr": "^0.8.5", "mini-css-extract-plugin": "^0.7.0", "node-sass": "^4.12.0", "optimize-css-assets-webpack-plugin": "^5.0.3", "postcss-loader": "^3.0.0", "rimraf": "^2.6.3", "sass-loader": "^7.1.0", "style-loader": "^0.23.1", "swiper": "^4.5.0", "uglifyjs-webpack-plugin": "^2.1.3", "url-loader": "^2.0.1", "vue-axios": "^2.1.4", "vue-lazyload": "^1.3.1", "vue-loader": "^15.7.0", "vue-style-loader": "^4.1.2", "vue-template-compiler": "^2.6.10", "vue-wechat-title": "^2.0.5", "vuex": "^3.1.1", "vuex-persistedstate": "^2.5.4", "webpack": "^4.35.2", "webpack-cli": "^3.3.5", "webpack-dev-server": "^3.7.2", "webpack-merge": "^4.2.1" }
這是個人我的的目錄結構(還在不斷的維護改善當中):ios
src文件夾存放業務代碼;build文件夾存放webpack的基礎配置;config文件夾統一存放配置參數;web
項目運行先從package.json中的 scripts執行加載配置啓動項目vue-router
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.dev.config.js", "clean": "rimraf dist", "build:pro": "cross-env NODE_ENV=production webpack --config build/webpack.prod.config.js", "build": "npm run clean && npm run build:pro" },
我這裏用了熱加載,區分開發環境和生產環境,執行npm run dev 會找到基礎配置文件 build/webpack.dev.config.js
開發環境配置 --build/webpack.dev.config.js 生產環境配置 --build/webpack.prod.config.js 提取公共基礎配置文件 --build/webpack.base.config.js 使用 webpack-merge合併配置文件
/* 1.配置webpack編譯入口 2.配置webpack輸出路徑和命名規則 3.配置模塊resolve規則 4.配置不一樣類型模塊的處理規則 */ 'use strict'; const path = require('path'); // node.js的文件路徑,用來處理文件當中的路徑問題 const baseconfig = require('../config'); //基礎環境變量的配置信息 const utils = require('./utils'); //處理css的工具包 const isDev = process.env.NODE_ENV === 'development'; const vueLoaderConfig = require('./vue-loader.config'); // vue-loader.conf配置文件是用來解決各類css文件的,定義了諸如css,less,sass之類的和樣式有關的loader function resolve(dir) { return path.join(__dirname, '..', dir) } // 此函數是用來返回當前目錄的平行目錄的路徑,由於有個'..' const config = { context: path.resolve(__dirname, '../'), //基礎目錄(絕對路徑),用於從配置中解析入口點和加載程序 以應用程序爲根目錄 普通字符串表明子目錄 /表明絕對路徑根目錄 entry: { app: './src/main.js' }, // 定義入口文件 output: { path: baseconfig.build.assetsRoot,//路徑 // 打包生成的出口文件所放的位置 filename: '[name].js', // 打包生成app.js文件 // publicPath: process.env.NODE_ENV === 'production' ? // baseconfig.build.assetsPublicPath : baseconfig.dev.assetsPublicPath // 項目上線地址,也就是真正的文件引用路徑,若是是production環境,其實這裏都是'/' }, resolve: { extensions: ['.js', '.vue', '.json'], // 省略擴展名,比方說import index from '../js/index'會默認去找index文件,而後找index.js,index.vue,index.json文件 alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), } // 使用別名 使用上面的resolve函數,意思就是用@代替src的絕對路徑 }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig }, { test: /\.js$/, loader: 'babel-loader', include: [resolve('src'), resolve('test')] }, { test: /\.jsx$/, loader: 'babel-loader' }, { test: /\.css$/, use: [ 'style-loader', //將css以js形式插入HTML中 'css-loader', //專門處理css文件 ] }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000,// 文件大小小於10000則編譯成base64格式代碼 name: utils.assetsPath('resources/images/[name].[hash:8].[ext]') //指定輸出文件的名字 }, }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000,// 文件大小小於10000則編譯成base64格式代碼 name: utils.assetsPath('resources/mp4/[name].[hash:8].[ext]') //指定輸出文件的名字 } }, { test: /\.(woff2?|eot|ttf|otf|ico)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000,// 文件大小小於10000則編譯成base64格式代碼 name: utils.assetsPath('resources/icon/[name].[hash:8].[ext]') } } ] }, // 不一樣文件模塊使用不一樣的loader node: { setImmediate: false, dgram: 'empty', fs: 'empty', net: 'empty', tls: 'empty', child_process: 'empty', } //這些選項能夠配置是否 polyfill 或 mock 某些 Node.js 全局變量和模塊。這可使最初爲 Node.js 環境編寫的代碼,在其餘環境(如瀏覽器)中運行. }; module.exports = config;
/* 1.引入相關插件和配置 2.生成處理各類樣式的規則 3.配置開發環境,如熱更新、監聽端口號,是否自動打開瀏覽器等都在webpack中的devServer中配置完成 4.尋找可利用的端口和添加顯示程序編譯運行時的錯誤信息。*/ 'use strict'; const path = require('path'); //基礎環境變量的配置信息 const utils = require('./utils'); //處理css的工具包 const webpack = require('webpack'); // 引入webpack模塊 const merge = require('webpack-merge'); // 將基礎配置和開發環境配置或者生產環境配置合併在一塊兒的包管理 const baseWebpackConfig = require('./webpack.base.config'); // 引入基本webpack基本配置 const HtmlWebpackPlugin = require('html-webpack-plugin'); // 文件名及時更改,自動打包而且生成響應的文件在index.html裏面 const VueLoaderPlugin = require('vue-loader/lib/plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); //當前環境的host const HOST = process.env.HOST;// processs爲node的一個全局對象獲取當前程序的環境變量,即host //當前環境的port const PORT = process.env.PORT && Number(process.env.PORT); const baseconfig = require('../config'); const isDev = process.env.NODE_ENV === 'development'; const defaultPlugins = [ //webpack編譯過程當中以及頁面上判斷環境,js代碼中能夠引用到,用於區分環境 new webpack.DefinePlugin({ 'process.env': { NODE_ENV: isDev ? '"development"':'"production"' } }), new VueLoaderPlugin(), //HTMLPlugin:添加HTML入口,能夠設置基礎參數 new HtmlWebpackPlugin({ template: path.join(__dirname,'../index.html') }) ]; const devServer = { port: PORT || baseconfig.dev.port, //啓動監聽端口 disableHostCheck: true, host: HOST || baseconfig.dev.host, // 若是編譯過程當中有錯誤,將錯誤顯示到網頁上 overlay: baseconfig.dev.errorOverlay ? { warnings: false, errors: true } : false,// warning 和 error 都要顯示 compress: true,// 一切服務都啓動用gzip方式進行壓縮代碼 hot: true, // 只從新渲染頁面當前組件的效果,而不會刷新這個頁面,每次渲染時數據依然存在 //將沒有作映射的url路由地址,都映射到index.html中,即當使用 HTML5 History API 時,任意的 404 響應均可能須要被替代爲 index.html historyApiFallback: { rewrites: [ { from: /.*/, to: path.posix.join(baseconfig.dev.assetsPublicPath, 'index.html') }, ], }, open: baseconfig.dev.autoOpenBrowser, // 啓動webpack-dev-server時,自動打開網頁 proxy: baseconfig.dev.proxyTable,//接口代理 // 若是你有單獨的後端開發服務器API,而且但願在同域名下發送API請求,那麼代理某些URL將頗有用.簡稱就是API代理,中間件 需引入 http-proxy-middleware quiet: false, // necessary for FriendlyErrorsPlugin // 啓用quiet後,除了初始啓動信息以外的任何內容都不會被打印到控制檯。這也意味着來自的WebPack的錯誤或警告在控制檯不可見。 }; const devWebpackConfig = merge(baseWebpackConfig,{ // devtool:'#cheap-module-eval-source-map', //幫助頁面上調試代碼 module: { rules: [ { test: /\.scss/, //css預處理器 後綴名.scss use: [ 'vue-style-loader', //將css以js形式插入HTML中 'css-loader', //專門處理css文件 { loader: "postcss-loader", options: { sourceMap: true, //直接使用前面生成的sourceMap,編譯的效率會快點 } }, 'sass-loader' //專門處理sass文件,轉爲css文件,不處理css ] } ] }, devServer:devServer, plugins: defaultPlugins.concat([ //啓動hot加載的功能的plugin new webpack.HotModuleReplacementPlugin(),// 永遠不能用在生產模式,模塊熱更新,修改文件的內容,容許在運行時更新各類模塊,而無需進行徹底刷新。 new webpack.NamedModulesPlugin(), // 當進行熱更新時,相關文件名會被展現出來 new webpack.NoEmitOnErrorsPlugin(), // 跳過編譯時出錯的代碼並記錄,使編譯後運行時的包不會發生錯誤。 new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', inject: true }), // 該插件可自動生成一個 html5 文件或使用模板文件將編譯好的代碼注入進去 new CopyWebpackPlugin([//複製插件 { from: path.resolve(__dirname, '../static'), to: baseconfig.dev.assetsSubDirectory, ignore: ['.*']//忽略.*的文件 } ]) ]), }); module.exports = devWebpackConfig;
/* 1.合併基礎的webpack配置 2.配置樣式文件的處理規則,styleLoaders 3.配置webpack的輸出 4.配置webpack插件 5.gzip模式下的webpack插件配置 6.webpack-bundle分析 */ 'use strict'; const path = require('path'); // node.js的文件路徑,用來處理文件當中的路徑問題 const webpack = require('webpack'); // 引入webpack模塊 const CopyWebpackPlugin = require('copy-webpack-plugin'); // 在webpack中拷貝文件和文件夾 const merge = require('webpack-merge'); // 將基礎配置和開發環境配置或者生產環境配置合併在一塊兒的包管理 const baseWebpackConfig = require('./webpack.base.config'); // 引入基本webpack基本配置 const HtmlWebpackPlugin = require('html-webpack-plugin'); // 文件名即便更改,自動打包而且生成響應的文件在index.html裏面 const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');// 壓縮css代碼 const miniCssExtractPlugin=require("mini-css-extract-plugin"); // css單獨提取打包 //一個用來壓縮優化CSS大小的東西 const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); // 一個用來壓縮優化JS大小的東西 const VueLoaderPlugin = require('vue-loader/lib/plugin'); const env = require('../config/prod.env'); const utils = require('./utils'); const baseconfig = require('../config');//導入基礎配置 const serverConfig = require('../serverConfig.json');//導入,可修改的公共域名 const defaultPlugins = [ //webpack編譯過程當中以及頁面上判斷環境,js代碼中能夠引用到,用於區分環境 new webpack.DefinePlugin({ 'process.env': env }), new VueLoaderPlugin(), //HTMLPlugin:添加HTML入口,能夠設置基礎參數 new HtmlWebpackPlugin({ template: path.join(__dirname,'../index.html'), inject: true, minify: {//壓縮 removeComments: true,//刪除註釋 collapseWhitespace: true,//刪除空格 removeAttributeQuotes: true//刪除屬性的引號 }, chunksSortMode: 'dependency'//模塊排序,按照咱們須要的順序排序 }) ]; //讓打包的時候輸出可配置的文件 const GenerateAssetPlugin = require('generate-asset-webpack-plugin'); const createServerConfig = function(compilation){ return JSON.stringify(serverConfig); } // 引入生產環境 const webpackConfig = merge(baseWebpackConfig,{ // 這一部分會單獨打包成類庫文件,方便瀏覽器緩存 會生成一個vendor.js代碼,包含類庫代碼 entry: { app: path.join(__dirname, "../src/main.js"), }, output: { filename: utils.assetsPath('js/[name].[chunkHash:8].js'), path: baseconfig.build.assetsRoot, chunkFilename: utils.assetsPath('js/[id].[chunkHash].js') }, module: { rules: [ { test: /\.scss/, //css預處理器 後綴名.scss use: [ { loader:miniCssExtractPlugin.loader, options:{ publicPath: '../' } }, 'css-loader', //專門處理css文件 { loader: "postcss-loader", options: { sourceMap: true, //直接使用前面生成的sourceMap,編譯的效率會快點 } }, 'sass-loader' //專門處理sass文件,轉爲css文件,不處理css ] } ] }, optimization: { minimizer: [ new OptimizeCSSAssetsPlugin({}), ], splitChunks: { chunks: 'all' }, runtimeChunk: true // webpack相關代碼打包到一個文件中,好處:能夠規避新的模塊加入的時候,webpack給新的模塊加id後,插入的順序可能在中間,使後面模塊id變化,會致使打包出的hash產生變化,這樣hash就不能進行常緩存 }, plugins: defaultPlugins.concat([ new miniCssExtractPlugin({filename: 'css/main.[contentHash:8].css'}), //讓打包的時候輸入可配置的文件 new GenerateAssetPlugin({ filename: 'serverconfig.json', fn: (compilation, cb) => { cb(null, createServerConfig(compilation)); }, extraFiles: [] }), new CopyWebpackPlugin([ { from: path.resolve(__dirname, '../static'), to: path.join(__dirname, '../dist'), ignore: ['.*'] }, ]), ]) }); module.exports = webpackConfig;
/*utils是工具的意思,是一個用來處理css的文件*/ 'use strict'; const path = require('path'); const baseconfig = require('../config'); //導出文件的位置,根據環境判斷開發環境和生產環境,爲config文件中index.js文件中定義的build.assetsSubDirectory或dev.assetsSubDirectory exports.assetsPath = function (_path) { const assetsSubDirectory = process.env.NODE_ENV === 'production' ? baseconfig.build.assetsSubDirectory : baseconfig.dev.assetsSubDirectory //Node.js path 模塊提供了一些用於處理文件路徑的小工具① return path.posix.join(assetsSubDirectory, _path) }
'use strict';//嚴格模式 const path = require('path'); module.exports = { dev:{ // 開發環境下面的配置 assetsSubDirectory: './static',//子目錄,通常存放css,js,image等文件 assetsPublicPath: './',//根目錄 proxyTable: {},//可利用該屬性解決跨域的問題 host: 'localhost', // 地址 port: 8080, //端口號設置,端口號佔用出現問題可在此處修改 autoOpenBrowser: false,//是否在編譯(輸入命令行npm run dev)後打開http://localhost:8080/頁面,之前配置爲true,近些版本改成false,我的偏向習慣自動打開頁面 errorOverlay: true,//瀏覽器錯誤提示 notifyOnErrors: true,//跨平臺錯誤提示 poll: false, //使用文件系統(file system)獲取文件改動的通知devServer.watchOptions devtool: 'cheap-module-eval-source-map',//增長調試,該屬性爲原始源代碼(僅限行)不可在生產環境中使用 cacheBusting: true,//使緩存失效 cssSourceMap: true//代碼壓縮後進行調bug定位將很是困難,因而引入sourcemap記錄壓縮先後的位置信息記錄,當產生錯誤時直接定位到未壓縮前的位置,將大大的方便咱們調試 }, build: { // 生產環境下面的配置 index: path.resolve(__dirname, '../dist/index.html'),//index編譯後生成的位置和名字,根據須要改變後綴,好比index.php assetsRoot: path.resolve(__dirname, '../dist'),//編譯後存放生成環境代碼的位置 assetsSubDirectory: './static',//js,css,images存放文件夾名 assetsPublicPath: './',//發佈的根目錄,一般本地打包dist後打開文件會報錯,此處修改成./。若是是上線的文件,可根據文件存放位置進行更改路徑 productionSourceMap: true, devtool: '#source-map',//① //unit的gzip命令用來壓縮文件,gzip模式下須要壓縮的文件的擴展名有js和css productionGzip: false, productionGzipExtensions: ['js', 'css'], bundleAnalyzerReport: process.env.npm_config_report } }
主要是對預設(presets)和插件(plugins)進行配置,所以不一樣的轉譯器做用不一樣的配置項
一、建立預設(presets):主要經過npm安裝babel-preset-xx插件來配合使用,例如經過 npm install babel-preset-stage-2 babel-preset-env --D 安裝,會有相應以下配置。
{ "presets": [ ["env", { "modules": false, "targets": { "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] } }], "stage-2" ], }
二、插件(plugins):官方推薦使用babel-preset-env來替代一些插件包的安裝
這裏主要介紹兩款經常使用插件,分別是babel-plugin-transform-runtime,babel-plugin-syntax-dynamic-import(若是.babelrc配置項中使用了"stage-2",也能夠不使用該插件,一樣支持動態模塊引入)。
{
"plugins": ["transform-vue-jsx", "transform-runtime","syntax-dynamic-import"]
}
完整的.babelrc文件內容:
{ "presets": [ ["env", { "modules": false, "targets": { "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] } }], "stage-2" ], "plugins": ["transform-vue-jsx", "transform-runtime"] }
const autoprefixer = require('autoprefixer'); module.exports = { plugins: [ require('autoprefixer')({ "overrideBrowserslist": [ "defaults", "not ie < 11", "last 2 versions", "> 1%", "iOS 7", "last 3 iOS versions" ] }) ] }
在src下新建main.js與app.vue文件
main.js內容以下:
import Vue from 'vue' import 'babel-polyfill' import App from './app.vue' import VueRouter from 'vue-router' import store from './store/index.js' import axios from 'axios' import Lockr from 'lockr' import VueAxios from 'vue-axios' import './assets/css/common.scss' import './assets/iconfont/iconfont.css' import VueLazyload from 'vue-lazyload' //圖片懶加載 import VueWechatTitle from 'vue-wechat-title' Vue.use(VueWechatTitle); Vue.use(VueLazyload, { preLoad: 1, //預加載高度的比例 error: '', //圖像的src加載失敗 loading: '', //src的圖像加載 attempt: 1, //嘗試計數 listenEvents: [ 'scroll', 'mousewheel' ] //你想要監聽的事件,我我的喜歡所有監聽,方便 }); Vue.use(VueAxios,axios); Vue.use(VueRouter); Vue.use(Lockr); import createRouter from './router/index' import './assets/js/touch_screen' const router = createRouter(); router.beforeEach((to, from, next) => { if (to.meta.title) { document.title = to.meta.title } if (to.meta.requireAuth) { next(); } else { next(); } }); Vue.prototype.getConfigJson = function () { axios.get('serverConfig.json').then((result)=>{ Vue.prototype.ApiUrl =result.data.ApiUrl;//設置成Vue的全局屬性 ApiUrl:域名接口 new Vue({ router, store, render: (h) => h(App) }).$mount('#root'); }).catch((error)=>{ console.log(error) }) } Vue.prototype.getConfigJson();//調用聲明的全局方法
<template> <div id="app"> </div> </template> <script> import Lockr from 'lockr' export default { name: 'App', data(){ return{ msg:"", currentDate:'', } }, created() { this.currentDate = (new Date()).getHours(); console.log(this.currentDate) //在頁面刷新時將vuex裏的信息保存到localStorage裏(代碼中實現刷新) window.addEventListener("beforeunload",()=>{ Lockr.set("messageStore",JSON.stringify(this.$store.state)); }); //在頁面加載時讀取localStorage裏的狀態信息 Lockr.get("messageStore") && this.$store.replaceState(Object.assign(this.$store.state,JSON.parse(Lockr.get("messageStore")))); Lockr.rm('messageStore'); }, } </script> <style lang="scss" scoped></style>
到這裏項目就結束了,運行npm run dev運行,瀏覽器輸入loaclhost:8080
這是我寫的第一篇文章,寫的不怎麼好,只是用做記錄本身的所學,有什麼好的建議,能夠留言