您好,登錄后才能下訂單哦!
一、vue-cli介紹
vue-cli是一個用于快速搭建vue項目的 腳手架。
二、vue-cli安裝、更新
安裝過nodeJs 、cnpm 后,全局安裝vue-cli(以后其他項目可直接使用):
cnpm install -g vue-cli
更新:
cnpm update vue-cli
查看安裝成功否(有版本號就是成功,V大寫)
vue -V
查看npm注冊表里vue-cli版本號:
cnpm view vue-cli
三、vue-cli 使用
安裝過webpack 、vue-cli后,可以開始搭建vue項目:
vue init webpack <Project Name>
eg:右擊Git Base Here(如果你沒有用git ,你也可以按住shift鍵右擊選擇“在此處打開命令窗口”,或者 cmd :cd \project/lfxProject),如圖:
or
ps:ESLint(一個javascript代碼檢測工具)、unit tests(單元測試)、Nightwatch(一個e2e用戶界面測試工具)。
四、項目完成
項目結構如下:
各文件作用解析,如下:
1、build文件夾:
build文件夾的結構:
(1)build.js
'use strict' require('./check-versions')() //調用版本檢查 process.env.NODE_ENV = 'production' //將環境配置為生產環境 const ora = require('ora') //npm包 loading插件 const rm = require('rimraf') //npm包 用于刪除文件 const path = require('path')//npm包 文件路徑工具 const chalk = require('chalk')//npm包 在終端輸出帶顏色的文字 const webpack = require('webpack')//引入webpack.js const config = require('../config')//引入配置文件 const webpackConfig = require('./webpack.prod.conf')//引入生產環境配置文件 // 在終端顯示loading效果,并輸出提示 const spinner = ora('building for production...') spinner.start() //先遞歸刪除dist文件再生成新文件,避免冗余 rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { if (err) throw err webpack(webpackConfig, (err, stats) => { spinner.stop() if (err) throw err process.stdout.write(stats.toString({ colors: true, modules: false, children: false, chunks: false, chunkModules: false }) + '\n\n') if (stats.hasErrors()) { console.log(chalk.red(' Build failed with errors.\n')) process.exit(1) } console.log(chalk.cyan(' Build complete.\n')) console.log(chalk.yellow( ' Tip: built files are meant to be served over an HTTP server.\n' + ' Opening index.html over file:// won\'t work.\n' )) }) })
ps:require/export是一種nodeJs(commonJs規范)的依賴注入的方法,import/export是ES6語法,用于引入模塊,在nodeJs中使用的ES6語法最終會使用babel工具(babel-loader)轉化為ES5
(2)check-version.js:檢測node和npm的版本,實現版本依賴
'use strict' const chalk = require('chalk') const semver = require('semver')//檢查版本 const packageConfig = require('../package.json') const shell = require('shelljs')//shelljs 模塊重新包裝了 child_process,調用系統命令更加方便 function exec (cmd) {//返回通過child_process模塊的新建子進程,執行 Unix 系統命令后轉成沒有空格的字符串 return require('child_process').execSync(cmd).toString().trim() } const versionRequirements = [ { name: 'node', currentVersion: semver.clean(process.version),//使用semver格式化版本 versionRequirement: packageConfig.engines.node //獲取package.json中設置的node版本 } ] if (shell.which('npm')) { versionRequirements.push({ name: 'npm', currentVersion: exec('npm --version'),// 自動調用npm --version命令,并且把參數返回給exec函數,從而獲取純凈的版本號 versionRequirement: packageConfig.engines.npm }) } module.exports = function () { const warnings = [] for (let i = 0; i < versionRequirements.length; i++) { const mod = versionRequirements[i] //若版本號不符合package.json文件中指定的版本號,就報錯 if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { warnings.push(mod.name + ': ' + chalk.red(mod.currentVersion) + ' should be ' + chalk.green(mod.versionRequirement) ) } } if (warnings.length) { console.log('') console.log(chalk.yellow('To use this template, you must update following to modules:')) console.log() for (let i = 0; i < warnings.length; i++) { const warning = warnings[i] console.log(' ' + warning) } console.log() process.exit(1) } }
(3)utils.js:utils是工具的意思,是一個用來處理css的文件,這個文件包含了三個工具函數:
var path = require('path')// node自帶的文件路徑工具 var config = require('../config')// 配置文件 var ExtractTextPlugin = require('extract-text-webpack-plugin')// 提取css的插件 /** @method assertsPath 生成靜態資源的路徑(判斷開發環境和生產環境,為config文件中index.js文件中定義assetsSubDirectory) * @param {String} _path 相對于靜態資源文件夾的文件路徑 * @return {String} 靜態資源完整路徑 */ exports.assetsPath = function (_path) { var assetsSubDirectory = process.env.NODE_ENV === 'production' ? config.build.assetsSubDirectory : config.dev.assetsSubDirectory //nodeJs path提供用于處理文件路徑的工具;path.posix提供對路徑方法的POSIX(可移植性操作系統接口)特定實現的訪問(可跨平臺); path.posix.join與path.join一樣,不過總是以 posix 兼容的方式交互 return path.posix.join(assetsSubDirectory, _path) } /**@method cssLoaders 生成處理css的loaders配置,使用css-loader和postcssLoader,通過options.usePostCSS屬性來判斷是否使用postcssLoader中壓縮等方法 * @param {Object} option = {sourceMap: true,// 是否開啟 sourceMapextract: true // 是否提取css}生成配置 * @return {Object} 處理css的loaders配置對象 */ exports.cssLoaders = function (options) { options = options || {} var cssLoader = { loader: 'css-loader', options: { minimize: process.env.NODE_ENV === 'production', sourceMap: options.sourceMap } } /**@method generateLoaders 生成 ExtractTextPlugin對象或loader字符串 * @param {Array} loaders loader名稱數組 * @return {String|Object} ExtractTextPlugin對象或loader字符串 */ function generateLoaders (loader, loaderOptions) { var loaders = [cssLoader] if (loader) { loaders.push({ loader: loader + '-loader', options: Object.assign({}, loaderOptions, { sourceMap: options.sourceMap }) }) } // ExtractTextPlugin提取css(當上面的loaders未能正確引入時,使用vue-style-loader) if (options.extract) {// 生產環境中,默認為true return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader' }) } else {//返回vue-style-loader連接loaders的最終值 return ['vue-style-loader'].concat(loaders) } } return { css: generateLoaders(),//需要css-loader 和 vue-style-loader postcss: generateLoaders(),//需要css-loader、postcssLoader 和 vue-style-loader less: generateLoaders('less'),//需要less-loader 和 vue-style-loader sass: generateLoaders('sass', { indentedSyntax: true }),//需要sass-loader 和 vue-style-loader scss: generateLoaders('sass'),//需要sass-loader 和 vue-style-loader stylus: generateLoaders('stylus'),//需要stylus-loader 和 vue-style-loader styl: generateLoaders('stylus')//需要stylus-loader 和 vue-style-loader } } /**@method styleLoaders 生成 style-loader的配置 * @param {Object} options 生成配置 * @return {Array} style-loader的配置 */ exports.styleLoaders = function (options) { var output = [] var loaders = exports.cssLoaders(options) //將各種css,less,sass等綜合在一起得出結果輸出output for (var extension in loaders) { var loader = loaders[extension] output.push({ test: new RegExp('\\.' + extension + '$'), use: loader }) } return output }
(4)vue-loader.conf.js:處理.vue文件,解析這個文件中的每個語言塊(template、script、style),轉換成js可用的js模塊。
'use strict' const utils = require('./utils') const config = require('../config') const isProduction = process.env.NODE_ENV === 'production' //生產環境,提取css樣式到單獨文件 const sourceMapEnabled = isProduction ? config.build.productionSourceMap : config.dev.cssSourceMap module.exports = { loaders: utils.cssLoaders({ sourceMap: sourceMapEnabled, extract: isProduction }), cssSourceMap: sourceMapEnabled, cacheBusting: config.dev.cacheBusting, //編譯時將“引入路徑”轉換為require調用,使其可由webpack處理 transformToRequire: { video: ['src', 'poster'], source: 'src', img: 'src', image: 'xlink:href' } }
(5)webpack.base.conf.js:開發、測試、生產環境的公共基礎配置文件,配置輸出環境,配置模塊resolve和插件等
'use strict' const path = require('path')// node自帶的文件路徑工具 const utils = require('./utils')// 工具函數集合 const config = require('../config')// 配置文件 const vueLoaderConfig = require('./vue-loader.conf')// 工具函數集合 /** * 獲取"絕對路徑" * @method resolve * @param {String} dir 相對于本文件的路徑 * @return {String} 絕對路徑 */ function resolve(dir) { return path.join(__dirname, '..', dir) } module.exports = { context: path.resolve(__dirname, '../'), //入口js文件(默認為單頁面所以只有app一個入口) entry: { app: './src/main.js' }, //配置出口 output: { path: config.build.assetsRoot,//打包編譯的根路徑(dist) filename: '[name].js', publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath//發布路徑 }, resolve: { extensions: ['.js', '.vue', '.json'],// 自動補全的擴展名 //別名配置 alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'),// eg:"src/components" => "@/components" } }, module: { rules: [ //使用vue-loader將vue文件編譯轉換為js { test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig }, //通過babel-loader將ES6編譯壓縮成ES5 { test: /\.js$/, loader: 'babel-loader', include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] }, //使用url-loader處理(圖片、音像、字體),超過10000編譯成base64 { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('img/[name].[hash:7].[ext]') } }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('media/[name].[hash:7].[ext]') } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('fonts/[name].[hash:7].[ext]') } } ] }, //nodeJs全局變量/模塊,防止webpack注入一些nodeJs的東西到vue中 node: { setImmediate: false, dgram: 'empty', fs: 'empty', net: 'empty', tls: 'empty', child_process: 'empty' } }
(6)webpack.dev.conf.js:webpack配置開發環境中的入口
'use strict' const utils = require('./utils') const webpack = require('webpack') const config = require('../config') const merge = require('webpack-merge')//webpack-merge實現合并 const path = require('path') const baseWebpackConfig = require('./webpack.base.conf') const CopyWebpackPlugin = require('copy-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')//webpack的提示錯誤和日志信息的插件 const portfinder = require('portfinder')// 查看空閑端口位置,默認情況下搜索8000這個端口 const HOST = process.env.HOST const PORT = process.env.PORT && Number(process.env.PORT) const devWebpackConfig = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) }, devtool: config.dev.devtool,//調試模式 devServer: { clientLogLevel: 'warning', historyApiFallback: {//使用 HTML5 History API 時, 404 響應替代為 index.html rewrites: [ { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, ], }, hot: true,//熱重載 contentBase: false, // 提供靜態文件訪問 compress: true,//壓縮 host: HOST || config.dev.host, port: PORT || config.dev.port, open: config.dev.autoOpenBrowser,//npm run dev 時自動打開瀏覽器 overlay: config.dev.errorOverlay ? { warnings: false, errors: true } : false,// 顯示warning 和 error 信息 publicPath: config.dev.assetsPublicPath, proxy: config.dev.proxyTable,//api代理 quiet: true, //控制臺打印警告和錯誤(用FriendlyErrorsPlugin 為 true) watchOptions: {// 檢測文件改動 poll: config.dev.poll, } }, plugins: [ new webpack.DefinePlugin({ 'process.env': require('../config/dev.env') }), new webpack.HotModuleReplacementPlugin(),//模塊熱替換插件,修改模塊時不需要刷新頁面 new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. new webpack.NoEmitOnErrorsPlugin(),//webpack編譯錯誤的時候,中斷打包進程,防止錯誤代碼打包到文件中 // 將打包編譯好的代碼插入index.html new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', inject: true }), // 提取static assets 中css 復制到dist/static文件 new CopyWebpackPlugin([ { from: path.resolve(__dirname, '../static'), to: config.dev.assetsSubDirectory, ignore: ['.*']//忽略.*的文件 } ]) ] }) module.exports = new Promise((resolve, reject) => { portfinder.basePort = process.env.PORT || config.dev.port portfinder.getPort((err, port) => { //查找端口號 if (err) { reject(err) } else { //端口被占用時就重新設置evn和devServer的端口 process.env.PORT = port devWebpackConfig.devServer.port = port // npm run dev成功的友情提示 devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ compilationSuccessInfo: { messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], }, onErrors: config.dev.notifyOnErrors ? utils.createNotifierCallback() : undefined })) resolve(devWebpackConfig) } }) })
(7)webpack.dev.prod.js:webpack配置生產環境中的入口
'use strict' const path = require('path') const utils = require('./utils') const webpack = require('webpack') const config = require('../config') const merge = require('webpack-merge') const baseWebpackConfig = require('./webpack.base.conf') const CopyWebpackPlugin = require('copy-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') const ExtractTextPlugin = require('extract-text-webpack-plugin') const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') const UglifyJsPlugin = require('uglifyjs-webpack-plugin') const env = require('../config/prod.env') const webpackConfig = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true, usePostCSS: true }) }, devtool: config.build.productionSourceMap ? config.build.devtool : false,//是否開啟調試模式 output: { path: config.build.assetsRoot, filename: utils.assetsPath('js/[name].[chunkhash].js'), chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') }, plugins: [ new webpack.DefinePlugin({ 'process.env': env }), new UglifyJsPlugin({//壓縮js uglifyOptions: { compress: { warnings: false } }, sourceMap: config.build.productionSourceMap, parallel: true }), new ExtractTextPlugin({//提取靜態文件,減少請求 filename: utils.assetsPath('css/[name].[contenthash].css'), allChunks: true, }), new OptimizeCSSPlugin({//提取優化壓縮后(刪除來自不同組件的冗余代碼)的css cssProcessorOptions: config.build.productionSourceMap ? { safe: true, map: { inline: false } } : { safe: true } }), new HtmlWebpackPlugin({ //html打包壓縮到index.html filename: config.build.index, template: 'index.html', inject: true, minify: { removeComments: true,//刪除注釋 collapseWhitespace: true,//刪除空格 removeAttributeQuotes: true//刪除屬性的引號 }, chunksSortMode: 'dependency'//模塊排序,按照我們需要的順序排序 }), new webpack.HashedModuleIdsPlugin(), new webpack.optimize.ModuleConcatenationPlugin(), new webpack.optimize.CommonsChunkPlugin({ // node_modules中的任何所需模塊都提取到vendor name: 'vendor', minChunks (module) { return ( module.resource && /\.js$/.test(module.resource) && module.resource.indexOf( path.join(__dirname, '../node_modules') ) === 0 ) } }), new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', minChunks: Infinity }), new webpack.optimize.CommonsChunkPlugin({ name: 'app', async: 'vendor-async', children: true, minChunks: 3 }), new CopyWebpackPlugin([//復制static中的靜態資源(默認到dist里面) { from: path.resolve(__dirname, '../static'), to: config.build.assetsSubDirectory, ignore: ['.*'] } ]) ] }) if (config.build.productionGzip) { const CompressionWebpackPlugin = require('compression-webpack-plugin') webpackConfig.plugins.push( new CompressionWebpackPlugin({ asset: '[path].gz[query]', algorithm: 'gzip', test: new RegExp( '\\.(' + config.build.productionGzipExtensions.join('|') + ')$' ), threshold: 10240, minRatio: 0.8 }) ) } if (config.build.bundleAnalyzerReport) { const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin webpackConfig.plugins.push(new BundleAnalyzerPlugin()) } module.exports = webpackConfig
2、config文件夾:
config文件夾的結構:
(1) dev.env.js和prod.env.js:分別配置:開發環境和生產環境。這個可以根據公司業務結合后端需求配置需要區分開發環境和測試環境的屬性
'use strict' const merge = require('webpack-merge') const prodEnv = require('./prod.env') module.exports = merge(prodEnv, { NODE_ENV: '"development"' })
ps:webpack-merge用于實現合并類似于ES6的Object.assign()
'use strict' module.exports = { NODE_ENV: '"production"' }
(*注意屬性值要用“‘'”雙層引住),訪問(獲取值)時直接用:
process.env.屬性名
ps:process(進程)是nodejs的一個全局變量,process.env 屬性返回一個用戶環境信息的對象
(2)index.js配置解析:
'use strict'; const path = require('path'); module.exports = { // ===================開發環境配置 dev: { assetsSubDirectory: 'static',//靜態資源文件夾(一般存放css、js、image等文件) assetsPublicPath: '/',//根目錄 proxyTable: {},//配置API代理,可利用該屬性解決跨域的問題 host: 'localhost', // 可以被 process.env.HOST 覆蓋 port: 3030, // 可以被 process.env.PORT 覆蓋 autoOpenBrowser: true,//編譯后自動打開瀏覽器頁面 http://localhost:3030/("port + host",默認"false"),設置路由重定向自動打開您的默認頁面 errorOverlay: true,//瀏覽器錯誤提示 notifyOnErrors: true,//跨平臺錯誤提示 poll: false, //webpack提供的使用文件系統(file system)獲取文件改動的通知devServer.watchOptions(監控文件改動) devtool: 'cheap-module-eval-source-map',//webpack提供的用來調試的模式,有多個不同值代表不同的調試模式 cacheBusting: true,// 配合devtool的配置,當給文件名插入新的hash導致清除緩存時是否生成source-map cssSourceMap: true //記錄代碼壓縮前的位置信息,當產生錯誤時直接定位到未壓縮前的位置,方便調試 }, // ========================生產環境配置 build: { index: path.resolve(__dirname, '../dist/index.html'),//編譯后"首頁面"生成的絕對路徑和名字 assetsRoot: path.resolve(__dirname, '../dist'),//打包編譯的根路徑(默認dist,存放打包壓縮后的代碼) assetsSubDirectory: 'static',//靜態資源文件夾(一般存放css、js、image等文件) assetsPublicPath: '/',//發布的根目錄(dist文件夾所在路徑) productionSourceMap: true,//是否開啟source-map devtool: '#source-map',//(詳細參見:https://webpack.docschina.org/configuration/devtool) productionGzip: false,//是否壓縮 productionGzipExtensions: ['js', 'css'],//unit的gzip命令用來壓縮文件(gzip模式下需要壓縮的文件的擴展名有js和css) bundleAnalyzerReport: process.env.npm_config_report //是否開啟打包后的分析報告 } };
3、node_modules文件夾:
存放npm install時根據package.json配置生成的npm安裝包的文件夾
4、src文件夾:
我們需要在src文件夾中開發代碼,打包時webpack會根據build中的規則(build規則依賴于config中的配置)將src打包壓縮到dist文件夾在瀏覽器中運行
(1)assets文件:用于存放靜態資源(css、image),assets打包時路徑會經過webpack中的file-loader編譯(因此,assets需要使用絕對路徑)成js
(2)components文件夾:用來存放 .vue 組件(實現復用等功能,如:過濾器,列表項等)
(3)router文件夾:在router/index.js文件中配置頁面路由
(4)App.vue:是整個項目的主組件,所有頁面都是通過使用<router-view/>開放入口在App.vue下進行切換的(所有的路由都是App.vue的子組件)
(5)main.js:入口js文件(全局js,你可以在這里:初始化vue實例、require/import需要的插件、注入router路由、引入store狀態管理)
5、static文件夾:
webpack默認存放靜態資源(css、image)的文件夾,與assets不同的是:static在打包時會直接復制一個同名文件夾到dist文件夾里(不會經過編譯,可使用相對路徑)
6、其他文件:
(1).babelrc:瀏覽器解析的兼容配置,該文件主要是對預設(presets)和插件(plugins)進行配置,因此不同的轉譯器作用不同的配置項,大致可分為:語法轉義器、補丁轉義器、sx和flow插件
(2).editorconfig:用于配置代碼格式(配合代碼檢查工具使用,如:ESLint,團隊開發時可統一代碼風格),這里配置的代碼規范規則優先級高于編輯器默認的代碼格式化規則 。
(3).gitignore:配置git提交時需要忽略的文件
(4)postcssrc.js: autoprefixer(自動補全css樣式的瀏覽器前綴);postcss-import(@import引入語法)、CSS Modules(規定樣式作用域)
(5)index.html:項目入口頁面,編譯之后所有代碼將插入到這來
(6)package.json:npm的配置文件(npm install根據package.json下載對應版本的安裝包)
(7)package.lock.json:npm install(安裝)時鎖定各包的版本號
(8)README.md:項目使用說明
五、運行項目
在webStorm中打開項目,首先趕緊右擊Project進行如下操作(否則會卡死,還有各種其他方法參見:
1、啟動安裝:cnpm install
2、然后npm run dev:跑起來~
3、生成打包文件 :npm run build
然后你會發現項目多了個dist文件夾(用于部署到生產環境用,是打包壓縮之后的src文件夾)
了解 vue cli 3 參見本人博客:https://www.jb51.net/article/148100.htm
了解 node 、npm 安裝/更新/使用,參見本人博客 :https://www.jb51.net/article/157050.htm
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。