A brief discussion on Vue-cli command line tool
Vue.js 提供一个官方命令行工具,可用于快速搭建大型单页应用。vue-webpack-boilerplate,官方定义为:full-featured Webpack setup with hot-reload, lint-on-save, unit testing & css extraction.本文主要介绍了浅谈Vue-cli 命令行工具分析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望能帮助到大家。
目录结构:
├── README.md ├── build │ ├── build.js │ ├── utils.js │ ├── vue-loader.conf.js │ ├── webpack.base.conf.js │ ├── webpack.dev.conf.js │ └── webpack.prod.conf.js ├── config │ ├── dev.env.js │ ├── index.js │ └── prod.env.js ├── index.html ├── package.json ├── src │ ├── App.vue │ ├── assets │ │ └── logo.png │ ├── components │ │ └── Hello.vue │ └── main.js └── static
config 环境配置
config 配置文件用来配置 devServer 的相关设定,通过配置 NODE_ENV 来确定使用何种模式(开发、生产、测试或其他)
config |- index.js #配置文件 |- dev.env.js #开发模式 |- prod.env.js #生产模式
index.js
'use strict' const path = require('path'); module.exports = { dev: { // 路径 assetsSubDirectory: 'static', // path:用来存放打包后文件的输出目录 assetsPublicPath: '/', // publicPath:指定资源文件引用的目录 proxyTable: {}, // 代理示例: proxy: [{context: ["/auth", "/api"],target: "http://localhost:3000",}] // 开发服务器变量设置 host: 'localhost', port: 8080, autoOpenBrowser: true, // 自动打开浏览器devServer.open errorOverlay: true, // 浏览器错误提示 devServer.overlay notifyOnErrors: true, // 配合 friendly-errors-webpack-plugin poll: true, // 使用文件系统(file system)获取文件改动的通知devServer.watchOptions // source map cssSourceMap: false, // develop 下不生成 sourceMap devtool: 'eval-source-map' // 增强调试 可能的推荐值:eval, eval-source-map(推荐), cheap-eval-source-map, cheap-module-eval-source-map 详细:https://doc.webpack-china.org/configuration/devtool }, build: { // index模板文件 index: path.resolve(__dirname, '../dist/index.html'), // 路径 assetsRoot: path.resolve(__dirname, '../dist'), assetsSubDirectory: 'static', assetsPublicPath: '/', // bundleAnalyzerReport bundleAnalyzerReport: process.env.npm_config_report, // Gzip productionGzip: false, // 默认 false productionGzipExtensions: ['js', 'css'], // source map productionSourceMap: true, // production 下是生成 sourceMap devtool: '#source-map' // devtool: 'source-map' ? } }
dev.env.js
'use strict' const merge = require('webpack-merge'); const prodEnv = require('./prod.env'); module.exports = merge(prodEnv, { NODE_ENV: '"development"' }); prod.env.js 'use strict' module.exports = { NODE_ENV: '"production"' };
build Webpack配置
build |- utils.js #代码段 |- webpack.base.conf.js #基础配置文件 |- webpack.dev.conf.js #开发模式配置文件 |- webpack.prod.conf.js #生产模式配置文件 |- build.js #编译入口
实用代码段 utils.js
const config = require('../config') const path = require('path') exports.assetsPath = function (_path) { const assetsSubDirectory = process.env.NODE_ENV === 'production' ? config.build.assetsSubDirectory // 'static' : config.dev.assetsSubDirectory return path.posix.join(assetsSubDirectory, _path) // posix方法修正路径 } exports.cssLoaders = function (options) { // 示例: ({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) options = options || {}; // cssLoader const cssLoader = { loader: 'css-loader', options: { sourceMap: options.sourceMap } } // postcssLoader var postcssLoader = { loader: 'postcss-loader', options: { sourceMap: options.sourceMap } } // 生成 loader function generateLoaders (loader, loaderOptions) { const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] // 设置默认loader if (loader) { loaders.push({ loader: loader + '-loader', options: Object.assign({}, loaderOptions, { // 生成 options 对象 sourceMap: options.sourceMap }) }) } // 生产模式中提取css if (options.extract) { // 如果 options 中的 extract 为 true 配合生产模式 return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader' // 默认使用 vue-style-loader }) } else { return ['vue-style-loader'].concat(loaders) } } return { // 返回各种 loaders 对象 css: generateLoaders(), postcss: generateLoaders(), less: generateLoaders('less'), // 示例:[ // { loader: 'css-loader', options: { sourceMap: true/false } }, // { loader: 'postcss-loader', options: { sourceMap: true/false } }, // { loader: 'less-loader', options: { sourceMap: true/false } }, // ] sass: generateLoaders('sass', { indentedSyntax: true }), scss: generateLoaders('sass'), stylus: generateLoaders('stylus'), styl: generateLoaders('stylus') } } exports.styleLoaders = function (options) { const output = []; const loaders = exports.cssLoaders(options); for (const extension in loaders) { const loader = loaders[extension] output.push({ test: new RegExp('\\.' + extension + '$'), use: loader }) // 示例: // { // test: new RegExp(\\.less$), // use: { // loader: 'less-loader', options: { sourceMap: true/false } // } // } } return output } exports.createNotifierCallback = function () { // 配合 friendly-errors-webpack-plugin // 基本用法:notifier.notify('message'); const notifier = require('node-notifier'); // 发送跨平台通知系统 return (severity, errors) => { // 当前设定是只有出现 error 错误时触发 notifier 发送通知 if (severity !== 'error') { return } // 严重程度可以是 'error' 或 'warning' const error = errors[0] const filename = error.file && error.file.split('!').pop(); notifier.notify({ title: pkg.name, message: severity + ': ' + error.name, subtitle: filename || '' // icon: path.join(__dirname, 'logo.png') // 通知图标 }) } }
基础配置文件 webpack.base.conf.js
基础的 webpack 配置文件主要根据模式定义了入口出口,以及处理 vue, babel 等的各种模块,是最为基础的部分。其他模式的配置文件以此为基础通过 webpack-merge 合并。
'use strict' const path = require('path'); const utils = require('./utils'); const config = require('../config'); function resolve(dir) { return path.join(__dirname, '..', dir); } module.exports = { context: path.resolve(__dirname, '../'), // 基础目录 entry: { app: './src/main.js' }, output: { path: config.build.assetsRoot, // 默认'../dist' filename: '[name].js', publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath // 生产模式publicpath : config.dev.assetsPublicPath // 开发模式publicpath }, resolve: { // 解析确定的拓展名,方便模块导入 extensions: ['.js', '.vue', '.json'], alias: { // 创建别名 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src') // 如 '@/components/HelloWorld' } }, module: { rules: [{ test: /\.vue$/, // vue 要在babel之前 loader: 'vue-loader', options: vueLoaderConfig //可选项: vue-loader 选项配置 },{ test: /\.js$/, // babel loader: 'babel-loader', include: [resolve('src')] },{ // url-loader 文件大小低于指定的限制时,可返回 DataURL,即base64 test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, // url-loader 图片 loader: 'url-loader', options: { // 兼容性问题需要将query换成options limit: 10000, // 默认无限制 name: utils.assetsPath('img/[name].[hash:7].[ext]') // hash:7 代表 7 位数的 hash } },{ test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, // url-loader 音视频 loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('media/[name].[hash:7].[ext]') } },{ test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, // url-loader 字体 loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('fonts/[name].[hash:7].[ext]') } } ] }, node: { // 是否 polyfill 或 mock setImmediate: false, dgram: 'empty', fs: 'empty', net: 'empty', tls: 'empty', child_process: 'empty' } }
开发模式配置文件 webpack.dev.conf.js
开发模式的配置文件主要引用了 config 对于 devServer 的设定,对 css 文件的处理,使用 DefinePlugin 判断是否生产环境,以及其他一些插件。
'use strict' const webpack = require('webpack'); const config = require('../config'); const merge = require('webpack-merge'); const baseWebpackConfig = require('./webpack.base.conf'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const portfinder = require('portfinder'); // 自动检索下一个可用端口 const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin'); // 友好提示错误信息 const devWebpackConfig = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) // 自动生成了 css, postcss, less 等规则,与自己一个个手写一样,默认包括了 css 和 postcss 规则 }, devtool: config.dev.devtool,// 添加元信息(meta info)增强调试 // devServer 在 /config/index.js 处修改 devServer: { clientLogLevel: 'warning', // console 控制台显示的消息,可能的值有 none, error, warning 或者 info historyApiFallback: true, // History API 当遇到 404 响应时会被替代为 index.html hot: true, // 模块热替换 compress: true, // gzip host: process.env.HOST || config.dev.host, // process.env 优先 port: process.env.PORT || config.dev.port, // process.env 优先 open: config.dev.autoOpenBrowser, // 是否自动打开浏览器 overlay: config.dev.errorOverlay ? { // warning 和 error 都要显示 warnings: true, errors: true, } : false, publicPath: config.dev.assetsPublicPath, // 配置publicPath proxy: config.dev.proxyTable, // 代理 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(), // 热加载时直接返回更新的文件名,而不是id new webpack.NoEmitOnErrorsPlugin(), // 跳过编译时出错的代码并记录下来,主要作用是使编译后运行时的包不出错 new HtmlWebpackPlugin({ // 该插件可自动生成一个 html5 文件或使用模板文件将编译好的代码注入进去 filename: 'index.html', template: 'index.html', inject: true // 可能的选项有 true, 'head', 'body', false }), ] }) module.exports = new Promise((resolve, reject) => { portfinder.basePort = process.env.PORT || config.dev.port; // 获取当前设定的端口 portfinder.getPort((err, port) => { if (err) { reject(err) } else { process.env.PORT = port; // process 公布端口 devWebpackConfig.devServer.port = port; // 设置 devServer 端口 devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ // 错误提示插件 compilationSuccessInfo: { messages: [`Your application is running here: http://${config.dev.host}:${port}`], }, onErrors: config.dev.notifyOnErrors ? utils.createNotifierCallback() : undefined })) resolve(devWebpackConfig); } }) })
生产模式配置文件 webpack.prod.conf.js
'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 env = process.env.NODE_ENV === 'production' ? require('../config/prod.env') : require('../config/dev.env') const webpackConfig = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, // production 下生成 sourceMap extract: true, // util 中 styleLoaders 方法内的 generateLoaders 函数 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 webpack.optimize.UglifyJsPlugin({ // js 代码压缩还可配置 include, cache 等,也可用 babel-minify compress: { warnings: false }, sourceMap: config.build.productionSourceMap, parallel: true // 充分利用多核cpu }), // 提取 js 文件中的 css new ExtractTextPlugin({ filename: utils.assetsPath('css/[name].[contenthash].css'), allChunks: false, }), // 压缩提取出的css new OptimizeCSSPlugin({ cssProcessorOptions: config.build.productionSourceMap ? { safe: true, map: { inline: false } } : { safe: true } }), // 生成 html new HtmlWebpackPlugin({ filename: process.env.NODE_ENV === 'production' ? config.build.index : 'index.html', template: 'index.html', inject: true, minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true }, chunksSortMode: 'dependency' // 按 dependency 的顺序引入 }), new webpack.HashedModuleIdsPlugin(), // 根据模块的相对路径生成一个四位数的 hash 作为模块 id new webpack.optimize.ModuleConcatenationPlugin(), // 预编译所有模块到一个闭包中 // 拆分公共模块 new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: function (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([{ from: path.resolve(__dirname, '../static'), to: config.build.assetsSubDirectory, ignore: ['.*'] }])] }) if (config.build.productionGzip) { // gzip 压缩 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, // 10kb 以上大小的文件才压缩 minRatio: 0.8 // 最小比例达到 .8 时才压缩 }) ) } if (config.build.bundleAnalyzerReport) { // 可视化分析包的尺寸 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; webpackConfig.plugins.push(new BundleAnalyzerPlugin()); } module.exports = webpackConfig;
build.js 编译入口
'use strict' process.env.NODE_ENV = 'production'; // 设置当前环境为生产环境 const ora = require('ora'); //loading...进度条 const rm = require('rimraf'); //删除文件 'rm -rf' const chalk = require('chalk'); //stdout颜色设置 const webpack = require('webpack'); const path = require('path'); const config = require('../config'); const webpackConfig = require('./webpack.prod.conf'); const spinner = ora('正在编译...'); spinner.start(); // 清空文件夹 rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { if (err) throw err; // 删除完成回调函数内执行编译 webpack(webpackConfig, function (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'); //error if (stats.hasErrors()) { console.log(chalk.red(' 编译失败出现错误.\n')); process.exit(1); } //完成 console.log(chalk.cyan(' 编译成功.\n')) console.log(chalk.yellow( ' file:// 无用,需http(s)://.\n' )) }) })
相关推荐:
The above is the detailed content of A brief discussion on Vue-cli command line tool. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



When managing WordPress websites, you often encounter complex operations such as installation, update, and multi-site conversion. These operations are not only time-consuming, but also prone to errors, causing the website to be paralyzed. Combining the WP-CLI core command with Composer can greatly simplify these tasks, improve efficiency and reliability. This article will introduce how to use Composer to solve these problems and improve the convenience of WordPress management.

I encountered a tricky problem when developing a small application: the need to quickly integrate a lightweight database operation library. After trying multiple libraries, I found that they either have too much functionality or are not very compatible. Eventually, I found minii/db, a simplified version based on Yii2 that solved my problem perfectly.

During the development process, we often need to perform syntax checks on PHP code to ensure the correctness and maintainability of the code. However, when the project is large, the single-threaded syntax checking process can become very slow. Recently, I encountered this problem in my project. After trying multiple methods, I finally found the library overtrue/phplint, which greatly improves the speed of code inspection through parallel processing.

In the process of developing a website, improving page loading has always been one of my top priorities. Once, I tried using the Miniify library to compress and merge CSS and JavaScript files in order to improve the performance of the website. However, I encountered many problems and challenges during use, which eventually made me realize that Miniify may no longer be the best choice. Below I will share my experience and how to install and use Minify through Composer.

I'm having a tricky problem when developing a front-end project: I need to manually add a browser prefix to the CSS properties to ensure compatibility. This is not only time consuming, but also error-prone. After some exploration, I discovered the padaliyajay/php-autoprefixer library, which easily solved my troubles with Composer.

When developing PHP projects, you often encounter the problem that some functions or methods have been executed for too long, causing program timeout. I've tried multiple solutions, but the results are not satisfactory until I discovered the phpunit/php-invoker library. This library completely solved my problem by setting the timeout time to call the executable function.

When developing websites using CraftCMS, you often encounter resource file caching problems, especially when you frequently update CSS and JavaScript files, old versions of files may still be cached by the browser, causing users to not see the latest changes in time. This problem not only affects the user experience, but also increases the difficulty of development and debugging. Recently, I encountered similar troubles in my project, and after some exploration, I found the plugin wiejeben/craft-laravel-mix, which perfectly solved my caching problem.

When using TYPO3CMS for website development, you often encounter problems with installation and configuration extensions. Especially for beginners, how to properly install and configure TYPO3 and its extensions can be a headache. I had similar difficulties in my actual project and ended up solving these problems by using Composer and TYPO3CMSComposerInstallers.
