【vue系列之二】详解vue-cli 2.0配置文件

上次给大家分享的是用vue-cli快速搭建vue项目,虽然很省时间和精力,但想要真正搞明白,我们还需要对其原理一探究竟。

大家拿到一个项目,要快速上手,正确的思路是这样的:

首先,如果在项目有readme.md的情况下,大家要先读readme,项目的一些基本介绍,包括项目信息、运行的脚本、采用何种框架,以及项目维护者等信息通常都会有。一般在git上维护的项目都会有readme.md,不熟悉markdown语法的同学可以先了解下markdown入门。

第二步,要看package.json。现代的前端项目中通常都会有package.json文件。在package.json里,会介绍项目名称、版本、描述、作者、脚本、依赖包,对环境的要求,以及对浏览器要求。

 1 {
 2   "name": "uccn",
 3   "version": "1.0.0",
 4   "description": "uccn3.0",
 5   "author": "v_yangtianjiao <v_yangtianjiao@baidu.com>",
 6   "private": true,
   // 这里的脚本是分析项目的主要入口
7 "scripts": { 8 "dev": "node build/dev-server.js", 9 "start": "node build/dev-server.js", 10 "build": "node build/build.js", 11 "jsonp": "node build/jsonp-server.js" 12 },
   // 项目依赖
13 "dependencies": { 14 "fetch-jsonp": "^1.1.3", 15 "less": "^2.7.2", 16 "less-loader": "^4.0.4", 17 "stylus": "^0.54.5", 18 "stylus-loader": "^3.0.1", 19 "vue": "^2.4.2" 20 }, 21 "devDependencies": { 22 "autoprefixer": "^7.1.2", 23 "babel-core": "^6.22.1", 24 "babel-loader": "^7.1.1", 25 "babel-plugin-component": "^0.10.1", 26 "babel-plugin-transform-runtime": "^6.22.0", 27 "babel-preset-env": "^1.3.2", 28 "babel-preset-es2015": "^6.24.1", 29 "babel-preset-stage-2": "^6.22.0", 30 "babel-register": "^6.22.0", 31 "chalk": "^2.0.1", 32 "connect-history-api-fallback": "^1.3.0", 33 "copy-webpack-plugin": "^4.0.1", 34 "css-loader": "^0.28.0", 35 "cssnano": "^3.10.0", 36 "eventsource-polyfill": "^0.9.6", 37 "express": "^4.14.1", 38 "extract-text-webpack-plugin": "^2.0.0", 39 "file-loader": "^0.11.1", 40 "friendly-errors-webpack-plugin": "^1.1.3", 41 "html-webpack-plugin": "^2.28.0", 42 "http-proxy-middleware": "^0.17.3", 43 "opn": "^5.1.0", 44 "optimize-css-assets-webpack-plugin": "^2.0.0", 45 "ora": "^1.2.0", 46 "rimraf": "^2.6.0", 47 "semver": "^5.3.0", 48 "shelljs": "^0.7.6", 49 "url-loader": "^0.5.8", 50 "vue-loader": "^13.0.4", 51 "vue-style-loader": "^3.0.1", 52 "vue-template-compiler": "^2.4.2", 53 "webpack": "^2.6.1", 54 "webpack-bundle-analyzer": "^2.2.1", 55 "webpack-dev-middleware": "^1.10.0", 56 "webpack-hot-middleware": "^2.18.0", 57 "webpack-merge": "^4.1.0" 58 },
// 对node版本的以及npm版本的要求
59 "engines": { 60 "node": ">= 4.0.0", 61 "npm": ">= 3.0.0" 62 },
   // 浏览器要求,vue项目不支持ie8,因为ie8是es3,尚没有Object.defineProperty属性
63 "browserslist": [ 64 "> 1%", 65 "last 2 versions", 66 "not ie <= 8" 67 ] 68 }

上面的package.json是从实际vue项目中摘出来的,大家从package.json中就会对项目有一个大概的了解,最主要的是脚本部分。通过npm的自动化任务,可以很方便的执行配置文件中的脚本。通过配置  "jsonp": "node build/jsonp-server.js",可以方便的使用npm run jsonp命令,代替node build/jsonp-server.js或者更复杂的一系列命令。详细的npm自动化命令可以移步npm 自动化。

 

 现在的项目目录结构如上,我们从刚才的脚本入手。首先是启服务的脚本npm run dev,实际上是执行node build/dev-server.js,我们在build文件夹中找到dev-server.js,一步步分析。

/* eslint-disable */

// 首先检查node和npm的版本 require('./check-versions')()
// 获取配置文件中默认的配置
var config = require('../config')
// 如果node无法判断当前是开发环境还是生产环境,则使用config.dev.env.NODE_ENV作为当前的环境
if (!process.env.NODE_ENV) {process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) }var opn = require('opn')// 用来在起来服务之后,打开浏览器并跳转指定URL var path = require('path')// node自带文件路径工具 var express = require('express')// node框架express(本地开发的核心,起服务) var webpack = require('webpack')// webpack,压缩打包 var proxyMiddleware = require('http-proxy-middleware')// 中间件 var webpackConfig = require('./webpack.dev.conf')// 开发环境的webpack配置 var mockMiddleware = require('../config/dev.mock')// 开发环境本地mock数据中间件 var port = process.env.PORT || config.dev.port var autoOpenBrowser = !!config.dev.autoOpenBrowser var proxyTable = config.dev.proxyTablevar app = express()// 起服务 var compiler = webpack(webpackConfig)// webpack进行编译
// webpack-dev-middleware将编译的文件放在内存中,后续注入
var devMiddleware = require('webpack-dev-middleware')(compiler, {publicPath: webpackConfig.output.publicPath,quiet: true }) // 热加载 var hotMiddleware = require('webpack-hot-middleware')(compiler, {log: false,heartbeat: 2000 }) compiler.plugin('compilation', function (compilation) {compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {hotMiddleware.publish({ action: 'reload' })cb()}) })// proxy api requests
// proxyTable中的配置挂载到express中
Object.keys(proxyTable).forEach(function (context) {var options = proxyTable[context]if (typeof options === 'string') {options = { target: options }}app.use(proxyMiddleware(options.filter || context, options)) })// 处理后退的时候匹配资源 app.use(require('connect-history-api-fallback')())// 暂存在内存的webpack编译后的文件挂载到express上 app.use(devMiddleware)
// 将本地mock中间件挂载到express上 app.use(mockMiddleware);
// 热加载挂载到express上 app.use(hotMiddleware)// 拼static静态资源文件路径 var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
// express为静态资源提供服务 app.use(staticPath, express.static(
'./static'))var uri = 'http://localhost:' + portvar _resolve var readyPromise = new Promise(resolve => {_resolve = resolve })console.log('> Starting dev server...') devMiddleware.waitUntilValid(() => {console.log('> Listening at ' + uri + '\n')if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {opn(uri)}_resolve() }) // 通过配置的端口,自动打开浏览器,并跳转拼好的URL,至此,发开环境已经跑起来了 var server = app.listen(port)module.exports = {ready: readyPromise,close: () => {server.close()} }

在上面的dev-server中,有很多变量来自于./config/index.js和webpack.dev.conf.js,我们一个个看上述配置文件。

首先看./config/index.js,这里是整个项目主要的配置入口,我们在代码中一步步分析:

// node自带路径工具.
var path = require('path')
// 分为两种环境,dev和production
module.exports = {build: {env: require('./prod.env'),// 使用config/prod.env.js中定义的编译环境index: path.resolve(__dirname, '../dist/index.html'),// 编译输入的index.html文件。node.js中,在任何模块文件内部,可以使用__filename变量获取当前模块文件的带有完整绝对路径的文件名,assetsRoot: path.resolve(__dirname, '../dist'),// 编译输出的静态资源路径assetsSubDirectory: 'static',// 编译输出的二级目录assetsPublicPath: './', // 编译发布的根目录,可配置为资源服务器或者cdn域名productionSourceMap: false,//是否开启cssSourceMapproductionGzip: false,// 是否开启gzipproductionGzipExtensions: ['js', 'css'],// 需要用gzip压缩的文件扩展名
    bundleAnalyzerReport: process.env.npm_config_report},dev: {env: require('./dev.env'),port: 8989,// 起服务的端口autoOpenBrowser: true,assetsSubDirectory: 'static',assetsPublicPath: '/',proxyTable: {},// 需要代理的接口,可以跨域cssSourceMap: false}
}

接着我们分析webpack.dev.conf.js:

var utils = require('./utils')// 工具类
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')// 使用webpack配置合并插件
var baseWebpackConfig = require('./webpack.base.conf')
var HtmlWebpackPlugin = require('html-webpack-plugin')// 这个插件自动生成HTML,并注入到.html文件中
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')// 将hot-reload相对路径添加到webpack.base.conf的对应的entry前面
Object.keys(baseWebpackConfig.entry).forEach(function (name) {baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})

// webpack.dev.conf.js与webpack.base.conf.js中的配置合并 module.exports
= merge(baseWebpackConfig, {module: {rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })},// webpack-devtool有7种模式,cheap-module-eval-source-map模式是比较快的开发模式
 
  devtool: '#cheap-module-eval-source-map',plugins: [
  // 你可以理解为,通过配置了DefinePlugin,那么这里面的标识就相当于全局变量,你的业务代码可以直接使用配置的标识。
new webpack.DefinePlugin({'process.env': config.dev.env}),// hotModule插件让页面变动时,只重绘对应的模块,不会重绘整个HTML文件new webpack.HotModuleReplacementPlugin(),
  // 在编译出现错误时,使用 NoEmitOnErrorsPlugin 来跳过输出阶段。这样可以确保输出资源不会包含错误
new webpack.NoEmitOnErrorsPlugin(),// 将生成的HTML代码注入index.html文件new HtmlWebpackPlugin({filename: 'index.html',template: 'index.html',inject: true}),
  // friendly-errors-webpack-plugin用于更友好地输出webpack的警告、错误等信息
new FriendlyErrorsPlugin()] })

 刚才的webpack.dev.conf.js中有引到webpack.base.conf.js,我们就把他们一网打尽,继续看webpack.base.conf.js!

/* eslint-disable */
var path = require('path')// node自带的文件路径插件
var utils = require('./utils')// 工具类
var config = require('../config')// 上面说过的config/index
var vueLoaderConfig = require('./vue-loader.conf')// vue-loader.conf配置文件是用来解决各种css文件的,定义了诸如css,less,sass之类的和样式有关的loader
// 此函数是用来返回当前目录的平行目录的路径,
function resolve (dir) {return path.join(__dirname, '..', dir)
}module.exports = {entry: {uccn: './src/main.js'// 入口},output: {
  // 路径是config目录下的index.js中的build配置中的assetsRoot,也就是dist目录path: config.build.assetsRoot,filename:
'[name].js',
  // 上线地址,也就是真正的文件引用路径,如果是production生产环境,其实这里都是 '/'publicPath: process.env.NODE_ENV
=== 'production'? config.build.assetsPublicPath: config.dev.assetsPublicPath},
 // resolve是webpack的内置选项,顾名思义,决定要做的事情,也就是说当使用 import "jquery",该如何去执行这件事情,就是resolve配置项要做的,import jQuery from "./additional/dist/js/jquery" 这样会很麻烦,可以起个别名简化操作 resolve: {
  // 省略扩展名,比方说import index form '../js/index', 会默认去找index文件,然后找index.js,.vue,.josn.extensions: [
'.js', '.vue', '.json'],alias: {'vue$': 'vue/dist/vue.esm.js',
    // 使用上面的resolve函数,意思是用@代替src的绝对路径
'@': resolve('src'),}},
 // 不同的模块使用不同的loadermodule: {rules: [{
     // 对vue文件,使用vue-loader解析test:
/\.vue$/,loader: 'vue-loader',options: vueLoaderConfig},{
     // babel-loader把es6解析成es5test:
/\.js$/,loader: 'babel-loader',include: [resolve('src'), resolve('test')]},{
     // url-loader将文件大小低于下面option中limit的图片,转化为一个64位的DataURL,这样会省去很多请求,大于limit的,按[name].[hash:7].[ext]的命名方式放到了static/img下面,方便做cachetest:
/\.(png|jpe?g|gif|svg)(\?.*)?$/,loader: 'url-loader',options: {limit: 20000,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]')}}]} }

 至此,npm run dev起本地开发环境相关的配置文件基本说完了,接着说一下上面都用到的util工具类:

var path = require('path')
var config = require('../config')
// extract-text-webpack-plugin该插件的主要是为了抽离css样式,防止将样式打包在js中引起页面样式加载错乱的现象
var ExtractTextPlugin = require('extract-text-webpack-plugin')
// 返回资源文件路径,path.posix以posix兼容的方式交互,是跨平台的,如果是path.win32的话,只能在win上 exports.assetsPath
= function (_path) {var assetsSubDirectory = process.env.NODE_ENV === 'production'? config.build.assetsSubDirectory: config.dev.assetsSubDirectoryreturn path.posix.join(assetsSubDirectory, _path) }
// 通过判断是否是生产环境,配置不同的样式语言的loader配置 exports.cssLoaders
= function (options) {options = options || {}var cssLoader = {loader: 'css-loader',options: {minimize: process.env.NODE_ENV === 'production',sourceMap: options.sourceMap}}// 生成各种loader配置,通过传入不同的loader和option,将不同样式文件语言的loader拼好,push到loader配置中。function generateLoaders (loader, loaderOptions) {var loaders = [cssLoader]if (loader) {loaders.push({loader: loader + '-loader',options: Object.assign({}, loaderOptions, {sourceMap: options.sourceMap})})}// extract-text-webpack-plugin有三个参数,use指需要用什么loader去编译文件;fallback指编译后用什么loader去提取文件;还有一个publicfile用来覆盖项目路径if (options.extract) {return ExtractTextPlugin.extract({use: loaders,fallback: 'vue-style-loader'})} else {return ['vue-style-loader'].concat(loaders)}}// 对不同的样式语言,返回相应的loaderreturn {css: generateLoaders(),postcss: generateLoaders(),less: generateLoaders('less'),sass: generateLoaders('sass', { indentedSyntax: true }),scss: generateLoaders('sass'),stylus: generateLoaders('stylus'),styl: generateLoaders('stylus')} }// 生成处理不同的样式文件处理规则 exports.styleLoaders = function (options) {var output = []var loaders = exports.cssLoaders(options)for (var extension in loaders) {var loader = loaders[extension]output.push({test: new RegExp('\\.' + extension + '$'),use: loader})}return output }

———————————————— 华丽的分隔符 —————————————————

下面我们继续说npm run build,打包编译的一系列操作~

从package.json 中可以看出,npm run build,其实是执行了 node build/build.js,我们在build文件夹中找到build.js,build主要的工作是:检测node和npm版本,删除dist包,webpack构建打包,在终端输出构建信息并结束,如果报错,则输出报错信息。

require('./check-versions')()process.env.NODE_ENV = 'production'

// 在终端显示的旋转器插件 var ora = require('ora')
// 用于删除文件夹
var rm = require('rimraf') var path = require('path')
// 终端文字颜色插件
var chalk = require('chalk') var webpack = require('webpack') var config = require('../config') var webpackConfig = require('./webpack.prod.conf')var spinner = ora('building for production...') spinner.start()
// 删除dist文件夹,之后webpack打包 rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err
=> {if (err) throw errwebpack(webpackConfig, function (err, stats) {spinner.stop()if (err) throw errprocess.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'))}) })

build.js用到了webpack.prod.conf.js,他与webpack.base.conf.js merge之后,作为webpack配置文件,我们再看看webpack.prod.conf.js,主要做的工作是:
1.提取webpack生成的bundle中的文本,到特定的文件,使得css,js文件与webpack输出的bundle分离。

2.合并基本的webpack配置

3.配置webpack的输出,包括输出路径,文件名格式。

4.配置webpack插件,包括丑化代码。

5.gzip下引入compression插件进行压缩。

/* eslint-disable */
var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var CopyWebpackPlugin = require('copy-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
// 用于从webpack生成的bundle中提取文本到特定文件中的插件
// 可以抽取出css,js文件将其与webpack输出的bundle分离
var ExtractTextPlugin = require('extract-text-webpack-plugin') var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')var env = config.build.env // 合并基础的webpack配置 var webpackConfig = merge(baseWebpackConfig, {module: {rules: utils.styleLoaders({sourceMap: config.build.productionSourceMap,extract: true})},
 // 7中sourceMap上面有讲过devtool: config.build.productionSourceMap
? '#source-map' : false,
 // 配置webpack输出的目录,及文件命名规则output: {path: config.build.assetsRoot,filename: utils.assetsPath(
'js/[name].min.js'),chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')},
 // webpack插件配置plugins: [
// 同webpack.dev.conf.jsnew webpack.DefinePlugin({'process.env': env}),
  // 丑化代码
new webpack.optimize.UglifyJsPlugin({compress: {warnings: false},sourceMap: true}),// 抽离css文件到单独的文件new ExtractTextPlugin({filename: utils.assetsPath('css/[name].min.css')}),new OptimizeCSSPlugin({cssProcessorOptions: {safe: true}}),// 生成并注入index.htmlnew HtmlWebpackPlugin({filename: config.build.index,template: 'index.html',inject: true,minify: {removeComments: true,collapseWhitespace: false,removeAttributeQuotes: true },chunksSortMode: 'dependency'}),// keep module.id stable when vender modules does not changenew webpack.HashedModuleIdsPlugin(),split vendor js into its own filenew webpack.optimize.CommonsChunkPlugin({name: 'vendor',minChunks: function (module, count) {// any required modules inside node_modules are extracted to vendorreturn (module.resource &&/\.js$/.test(module.resource) &&module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0)}}),extract webpack runtime and module manifest to its own file in order toprevent vendor hash from being updated whenever app bundle is updatednew webpack.optimize.CommonsChunkPlugin({name: 'manifest',chunks: ['vendor']}),copy custom static assetsnew CopyWebpackPlugin([{from: path.resolve(__dirname, '../static'),to: config.build.assetsSubDirectory,ignore: ['.*']}])] }) // gzip模式下需要引入compression插件进行压缩 if (config.build.productionGzip) {var 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) {var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPluginwebpackConfig.plugins.push(new BundleAnalyzerPlugin()) }module.exports = webpackConfig

到此为止,vue官方脚手架工具vue-cli 2.0的所有配置文件都已介绍完毕,从头到尾再梳理一遍:

执行npm run dev或者npm run start,实际是在node环境执行build/dev-server.js, dev-server.js会去拿到config中的端口等配置,通过express起一个服务,通过插件自动打开浏览器,加载webpack编译后放在内存的bundle。

执行npm run build,实际上执行了build/build.js,通过webpack的一系列配置及插件,将文件打包合并丑化,并创建dist目录,放置编译打包后的文件,这将是未来用在生产环境的包。

 

写这篇文章我自身的收获也挺多,第一是对vue-cli整体的认知更加清晰条理,第二是对webpack的一些插件有了新的认识。以前对一些插件模棱两可,直接越过,这是不对的,要一步一个脚印儿,遇坑填坑,这样才会有收获。虽然过程可能是艰辛的,但收获将会是巨大的~

文章中不足之处希望大家多多指正!

参考文献:

extract-text-webpack-plugin 的使用及安装

vue-cli的webpack模板项目配置文件分析

webpack——devtool里的7种SourceMap模式

vue-cli#2.0 webpack 配置分析

__dirname与__filename

 

转载于:https://www.cnblogs.com/tjyoung/p/7652930.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/428684.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

4. Spring 如何通过 XML 文件配置Bean,以及如何获取Bean

在 Spring 容器内拼凑 bean 叫做装配。装配 bean 的时候&#xff0c;你是在告诉容器&#xff0c;需要哪些 bean &#xff0c;以及容器如何使用依赖注入将它们配合在一起。 理论上&#xff0c;bean 装配的信息可以从任何资源获得&#xff0c;包括属性文件&#xff0c;关系数据库…

基于用户击键特征的身份鉴别系统

简单来说&#xff0c;我们要做的就是一种通过用户敲击键盘的习惯进行身份鉴别的系统。国内外之前有一些相关研究&#xff0c;但是通常是数千条数据训练&#xff0c;而且不能随意改变敲击的字符串&#xff0c;或者是有的要求采用带有压力传感器的键盘&#xff0c;难以实用和推广…

常见三种字符编码的区别:ASCII、Unicode、UTF-8

什么是字符编码&#xff1f; 计算机只能处理数字&#xff0c;如果要处理文本&#xff0c;就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特&#xff08;bit&#xff09;作为一个字节&#xff08;byte&#xff09;&#xff0c;所以&#xff0c;一个字节能表…

导航,头部,CSS基础

制作自己的导航条。HTML头部元素&#xff1a;<base> 定义了页面链接标签的默认链接地址<style> 定义了HTML文档的样式文件<link> 定义了一个文档和外部资源之间的关系练习样式表&#xff1a;行内样式表内嵌样式表外部样式表分别练习定义三类选择器&#x…

十五、导航,头部,CSS基础

制作自己的导航条。HTML头部元素&#xff1a;<base> 定义了页面链接标签的默认链接地址<style> 定义了HTML文档的样式文件<link> 定义了一个文档和外部资源之间的关系 练习样式表&#xff1a;行内样式表内嵌样式表外部样式表分别练习定义三类选择器&#…

【网络爬虫入门04】彻底掌握BeautifulSoup的CSS选择器

【网络爬虫入门04】彻底掌握BeautifulSoup的CSS选择器 广东职业技术学院 欧浩源 2017-10-21 1、引言 目前&#xff0c;除了官方文档之外&#xff0c;市面上及网络详细介绍BeautifulSoup使用的技术书籍和博客软文并不多&#xff0c;而在这仅有的资料中介绍CSS选择器的少之又少。…

Mybatis基于XML配置SQL映射器(一)

Durid和Mybatis开发环境搭建 SpringBoot搭建基于SpringSpringMvcMybatis的REST服务&#xff08;http://www.cnblogs.com/nbfujx/p/7694768.html&#xff09; Mybatis之代码生成器 Maven Plugin管理 1 <build>2 <plugins>3 <plugin>4 …

linux运维、架构之路-Zabbix监控

一、监控常用命令 1、物理服务器监控命令 ①添加yum源 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo ②安装 yum -y install OpenIPMI ipmitoo…

vi命令

vi命令是UNIX操作系统和类UNIX操作系统中最通用的全屏幕纯文本编辑器。 Linux中的vi编辑器叫vim&#xff0c;它是vi的增强版&#xff08;vi Improved&#xff09;&#xff0c;与vi编辑器完全兼容&#xff0c;而且实现了很多增强功能。 vi编辑器支持编辑模式和命令模式&#xff…

SQL基本语法

SQL 基本语法 表库操作 创建表create table 表名(字段名 类型(长度) 约束,字段名 类型(长度) 约束); 创建主键约束id int primary key, primary key(id) // 在创建表最后创建主键约束 删除主键alter table 表名 drop primary key; 主键自动增长主键字段后加auto_increment(只适…

KindEditor富文本编辑器上传功能PHP语言报错问题

问题产生过程&#xff1a;项目原本使用的是Ueditor编辑器&#xff0c;由于其中js代码有使用parentNode获取HTML节点&#xff0c;IE浏览器内核不支持parentNode &#xff0c;会有二次加载富文本编辑器不渲染的问题&#xff0c;所以更换编辑器为kindeditor&#xff0c;其中上传文…

二、PyCharm 创建Django 第一个项目

PyCharm 下创建Django项目 File->New Project->Django 目录说明&#xff1a; dj: 项目的容器。manage.py: 一个实用的命令行工具&#xff0c;可让你以各种方式与该 Django 项目进行交互。dj/__init__.py: 一个空文件&#xff0c;告诉 Python 该目录是一个 Python 包。dj/…

linux last failed login表示什么意思_Linux用户

Linux的用户在登录(login)之后&#xff0c;就带有一个用户身份(user ID, UID)和一个组身份(group ID, GID)。在Linux文件管理背景知识中&#xff0c;我们又看到&#xff0c;每个文件又有九位的权限说明&#xff0c;用来指明该文件允许哪些用户执行哪些操作(读、写或者执行)。(参…

CSS3详解:transform、transition

CSS3 transform是什么&#xff1f; transform的含义是&#xff1a;改变&#xff0c;使…变形&#xff1b;转换 CSS3 transform都有哪些常用属性&#xff1f; transform的属性包括&#xff1a;rotate() / skew() / scale() / translate(,) &#xff0c;分别还有x、y之分&#xf…

c++ 线程什么时候run_多线程并发支撑基础之JAVA内存模型

Java内存模型可以说是Java并发的底层支持&#xff0c;了解Java内存模型才能正在了解Java并发。内存模型在内存中设置一个变量"value 1&#xff1b;"那么其他线程能在什么时候读取到这个结果呢&#xff1f;有可能不能立即甚至永远都读不到。比如指令顺序与源代码中的…

润乾报表 数据集ds1中,数据源xmglxt_x3无数据库连接,且未设定数据连接工厂,请检查数据源设定:...

一、润乾报表错误内容 产生数据工厂: com.runqian.report4.dataset.SQLDataSetFactory 失败 错误来源&#xff1a;: 数据集ds1中&#xff0c;数据源xmglxt_x3无数据库连接&#xff0c;且未设定数据连接工厂&#xff0c;请检查数据源设定&#xff1a; 二、解决方法 同事做的润乾…

WPF中的数据绑定Data Binding使用小结

完整的数据绑定的语法说明可以在这里查看&#xff1a; http://www.nbdtech.com/Free/WpfBinding.pdf MSDN资料&#xff1a; Data Binding: Part 1 http://msdn.microsoft.com/en-us/library/aa480224.aspx Data Binding: Part 2 http://msdn.microsoft.com/en-us/library/aa480…

Swift 将日期转化为字符串,显示上午还是下午

let dateF DateFormatter() // aaa 用于显示上午还是下午&#xff0c;mm和MM 分别表示12小时制和24小时制 dateF.dateFormat "yyyy-MM-dd aaa hh:mm:ss" dateF.amSymbol "上午" dateF.pmSymbol "下午" let str dateF.string(from: Date()) …

车间生产能耗管控方案_如何给生产车间降温 环保空调的这些方案一定能帮到你...

生产车间闷热如何降温&#xff1f;高温闷热带来的影响是非常大&#xff0c;在厂房车间闷热的环境会影响作业人员的情绪&#xff0c;增加燥热感&#xff0c;使工作效率下降&#xff0c;生产力降低&#xff0c;产品质量变差&#xff0c;蕞严重的结果导致客户流失&#xff0c;所以…

app开发人脸登录和指纹登录_易讯云通讯推出“一键登录”,为App登录提供新方案...

移动互联网时代&#xff0c;用户的耐心越来越少&#xff0c;注意力也越来越弱&#xff0c;追求便捷与高效。登录的方式从自定义的账号密码登录&#xff0c;到邮箱登录&#xff0c;到第三方登录与手机验证码登录两种登录方式进行竞争&#xff0c;到现在的个人指纹&#xff0c;人…