1 2 3 4 5 6 7 8 9 10 |
Mac系统从10.12 macOS Sierra更新到10.13.2macOS High Sierra后执行git命令报错 xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun 解决方法: xcode-select --install 安装即可。 |
解决React首屏加载白屏的问题
众所周知,在项目中如果在资源加载请求还未完成的时候,由于阻塞机制,会出现首页白屏的问题,产生很差的用户体验。本文以react为例,提供一个解决方法。
解决原理:使用 onreadystatechange 去监听 readyState,在资源加载完成之前加载一个只有框架的静态页面,页面不请求[……]
webpack 3.8 使用 extract-text-webpack-plugin 3.0 抽取css失败:You may need an appropriate loader to handle this file type.
1 2 3 4 5 6 7 8 9 10 11 12 |
webpack 3.8.1 使用 extract-text-webpack-plugin 3.0.2 抽取css时失败,报错: ERROR in ./src/static/style/localTime.css Module parse failed: Unexpected token (1:0) You may need an appropriate loader to handle this file type. | .localTimeBox { | color: red; | } @ ./node_modules/style-loader!./src/static/style/localTime.css 4:14-42 webpack-build.config.js 配置为: |
1 2 3 4 5 6 7 8 9 10 11 |
module: { loaders: [ { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'style-loader!css-loader', {publicPath: '../'}) } ] }, plugins: [ new ExtractTextPlugin('css/bundle.min.css', {allChunks: true}) ] |
解决方法:
将webpack-build.config.js 配置改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
module: { loaders: [ { test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader'], publicPath: '../' }) } ] }, plugins: [ new ExtractTextPlugin('css/bundle.min.css', {allChunks: true}) ] |
问题就解决了。[……]
Cannot resolve symbol ‘Component’ & Cannot resolve symbol ‘PropTypes’
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import React, { Component, PropTypes } from 'react' 报错:Cannot resolve symbol 'Component' Cannot resolve symbol 'PropTypes' 1.解决 Cannot resolve symbol 'Component' 安装依赖:npm install @types/react --save 调用方法:import React, { Component } from 'react' 2.解决 Cannot resolve symbol 'PropTypes' 安装依赖:npm install prop-types --save 调用方法:import PropTypes from 'prop-types' 注:React.PropTypes 自 React v15.5 起已弃用。请使用 prop-types 库代替。 |
React & Redux 的一些基本知识点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
一、React.createClass 跟 React.Component 的区别在于后者使用了ES6的语法,用constructor构造器来构造默认的属性和状态。 1. React.createClass import React from 'react'; const Contacts = React.createClass({ render() { return ( <div></div> ); } }); export default Contacts; 2.React.Component import React from 'react'; class Contacts extends React.Component { constructor(props) { super(props); } render() { return ( <div></div> ); } } export default Contacts; 二、 Super(props) 调用父类的构造函数,react希望把所有props,state的定义尽量放到父类中进行。 子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象, 而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。 三、容器组件 Container Components 和展示组件 Presentational Components -------------------------------------------------------------------------- | 展示组件 | 容器组件 -------------------------------------------------------------------------- 作用 | 描述如何展现(骨架、样式) | 描述如何运行(数据获取、状态更新) -------------------------------------------------------------------------- 直接使用Redux | 否 | 是 -------------------------------------------------------------------------- 数据来源 | props | 监听 Redux state -------------------------------------------------------------------------- 数据修改 | 从 props 调用回调函数 | 向 Redux 派发 actions -------------------------------------------------------------------------- 调用方式 | 手动 | 通常由 React Redux 生成 -------------------------------------------------------------------------- <strong>四、connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])</strong> 连接 React 组件与 Redux store。连接操作不会改变原来的组件类,而是返回一个新的已与 Redux store 连接到组件类。 1.[mapStateToProps(state, [ownProps]): stateProps] (Function): 如果定义该参数,组件将会监听 Redux store 的变化。只要 Redux store 发生变化,mapStateToProps函数就会被调用。 该回掉函数必须返回一个纯对象,这个对象与组件的props合并。如果省略了这个参数,组件将不会监听 Redux store。 如果指定了第二个参数 ownProps,则该参数的值为传递到之间的props,而且只要组件接收到新的 props, mapStateToProps也会被调用。 2.[mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function): 如果传递的是一个对象,那么每个定义在该对象的函数都将被当作 Redux action creator, 对象所定义的方法名将作为属性名;每个方法将返回一个新的函数,函数中dispatch方法会将action creator的返回值作为参数执行。 这些属性会被合并到组件的 props 中。如果传递的是一个函数,该函数将接收一个 dispatch 函数,然后由你来决定如何返回一个对象, 这个对象通过 dispatch 函数与 action creator 以某种方式绑定在一起(提示:你也许会用到 Redux 的辅助函数 bindActionCreators())。 如果你省略这个 mapDispatchToProps 参数,默认情况下,dispatch 会注入到你的组件 props 中。 如果指定了该回调函数中第二个参数 ownProp该参数的值为传递到组件的 props,而且只要组件接收到新 props,mapDispatchToProps 也会被调用。 3.[mergeProps(stateProps, dispatchProps, ownProps): props] (Function): 如果指定了这个参数,mapStateToProps() 与 mapDispatchToProps() 的执行结果和组件自身的 props 将传入到这个回调函数中。 该回调函数返回的对象将作为 props 传递到被包装的组件中。你也许可以用这个回调函数,根据组件的 props 来筛选部分的 state 数据, 或者把 props 中的某个特定变量与 action creator 绑定在一起。如果你省略这个参数,默认情况下返回 Object.assign({}, ownProps, stateProps, dispatchProps) 的结果。 4.[options] (Object): 如果指定这个参数,可以定制 connector 的行为。 [pure = true] (Boolean): 如果为 true,connector 将执行 shouldComponentUpdate 并且浅对比 mergeProps 的结果, 避免不必要的更新,前提是当前组件是一个“纯”组件,它不依赖于任何的输入或 state 而只依赖于 props 和 Redux store 的 state。默认值为 true。[withRef = false] (Boolean): 如果为 true,connector 会保存一个对被包装组件实例的引用, 该引用通过 getWrappedInstance() 方法获得。默认值为 false。 |
react-router 3 中的 useRouterHistory(createHistory) 到了 react-router 4 变成了什么?
react-router 3 文档: https://github.com/ReactTraining/react-router/blob/v3/docs/API.md
react-router 4 文档: https://reacttraining.com/react-router[……]
react-router 4 文档: https://reacttraining.com/react-router[……]
一个 React & Redux的目录树
React & Redux
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
Project | |-- node_modules | | | |-- react | | | |-- react-dom | | | |-- react-router | | | |-- react-redux => redux本身只能处理同步的Action | | | |-- react-thunk => 在我们没有加上thunk这个中间件之前, | | store的dispatch方法只能传入一个action对象, | | thunk的作用就是能够让我们可以将一个function方法传入diptach, | | 这在做异步的时候非常有用。 | | | |-- redux-promise => redux-promise支持将promise对象作为参数传入dispatch中。 | | | |-- prop-types => React.PropTypes 自 React v15.5 起已弃用。 | | 请使用 prop-types 库代替。调用方法: | | import PropTypes from 'prop-types' | | | |-- @types/react => implements method in React.Component,解决 | | Cannot resolve symbol 'Component' 的问题 | | | |-- postcss-loader => PostCSS,一款通过 JS 插件转换 styles 样式的工具。 | | 根目录下新建postcss.config.js文件。配置如下: | | module.exports = { | | parser: 'sugarss', | | plugins: { | | 'postcss-import': {}, | | 'postcss-cssnext': {}, | | 'cssnano': {} | | } | | } | | webpack配置:{ | | test: /\.css$/, | | use: ['style-loader', 'css-loader','postcss-loader'] | | } | | | |-- Autoprefixer => PostCSS插件,一个后处理程序。解析CSS并添加浏览器前缀。 | | postcss.config.js文件中配置如下: | | module.exports = { | | plugins: [ | | require('autoprefixer')({}) | | ] | | } | | | |-- extract-text-webpack-plugin => 将css单独打包成一个文件。 | | 它会将所有的入口 chunk(entry chunks)中引用的 *.css, | | 移动到独立分离的 CSS 文件。因此,你的样式将不再内嵌到JS bundle中, | | 而是会放到一个单独的 CSS 文件(即 styles.css)当中。 | | 如果你的样式文件大小较大,这会做更快提前加载,因为 CSS bundle | | 会跟 JS bundle 并行加载。 | | | |-- optimize-css-assets-webpack-plugin => 压缩抽离后的css代码, | | plugins: [new OptimizeCssAssetsPlugin()] | | | |-- html-webpack-plugin => 该插件将为您生成一个HTML5文件, | | 其中包括使用script标签的body中的所有webpack包。 | | | |-- copy-webpack-plugin => 在webpack中拷贝文件和文件夹。例如: | | new CopyWebpackPlugin([ | | {from: "./src/static/images", to: 'images/'} | | ]) | | 作用就是将 ./src/static/images | | 目录下的图片拷到编译目录到 images 文件夹下面 | | | |-- rimraf => 编译前清空dist目录。package.json配置: | | "scripts": {"build": "rimraf dist && ..."} | | | |-- OpenBrowserPlugin => webpack编译后自动打开浏览器 | | | |-- axios => 一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中 | | | |-- babel-eslint => 一个Babel parser的包装器,这个包装器使得Babel parser可以和ESLint协调工作 | | .eslintrc.js中配置:"parser": "babel-eslint", | | "parserOptions": { | | "sourceType": "module", | | "allowImportExportEverywhere": false, | | "codeFrame": false | | } | | | |-- webpack | | | |-- webpack-dev-middleware | | | |-- webpack-hot-middleware | |-- dist => 打包输出文件目录 | |-- src | | | |-- actions => Action是把数据从应用传到 store 的有效载荷。 | | 它是 store 数据的唯一来源,一般通过 | | store.dispatch() 将 action 传到 store。 | | | |-- reducers => Action只是描述了有事情发生了这一事实, | | 并没有指明应用如何更新 state。 | | reducer 用来做更新state这个动作。 | | | |-- store => 1.维持应用的state; | | 2.提供 getState() 方法获取 state; | | 3.提供 dispatch(action) 方法更新state; | | 4.通过 subscribe(listener) 注册监听器; | | 5.通过 subscribe(listener) 返回的函数注销监听器。 | | | |-- components => 展示型组件目录 | | | |-- containers => 容器型组件目录 | | | |-- config => 配置actionType、接口 | | | |-- library => 插件库 | | | |-- service => 服务配置 | | | |-- static => 静态文件目录 | | | |-- main.js => 入口文件 | |-- webpack => webpack配置目录 | |-- .babelrc => Bable的配置文件,用来设置转码规则和插件。 | Babel是一个广泛使用的ES6转码器, | 可以将ES6代码转为ES5代码。 | |-- .gitignore => git上传忽略特殊文件配置 | |-- index.html | |-- README.md | |-- package.json => 定义了这个项目所需要的各种模块,以及项目的配置信息。 | |-- package-lock.json => npm5.0后新增。记录了整个 node_modules | 文件夹的树状结构,当重新安装模块的时候, | 速度加快。但是,生成pack-lock.json后, | 重复执行npm install时将会以其记录的版本来安装。 | 这时如果手动修改 package.json 中的版本, | 重新安装也不会生效,只能手动执行npm install | 命令指定依赖版本来进行修改。 | | |-- yarn.lock => yarn.lcok文件是自动产生的, | 和package-lock.json的功能一样, | 只不过yarn可以做到手动更改package.json后, | 重新安装并更新lockfile。 |
vue中使用 echarts3.0 或 echarts2.0
一、echarts3.0(官网: http://echarts.baidu.com/)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
首先通过npm安装echarts依赖,安装的为3.0版本 npm install echarts -s 也可以使用淘宝镜像 npm install -g cnpm --registry=https://registry.npm.taobao.org cnpm install echarts -s 引入的方式有两种: 1、main.js中全局引入 import echarts from 'echarts' Vue.prototype.$echarts = echarts 然后在组件中通过 this.$echarts.init(document.getElementById('your_div')) 来初始化 2、只应用基本包,加快加载速度 在需要使用echarts的组建中引入: let echarts = require('echarts/lib/echarts') 然后通过 echarts.init(document.getElementById('your_div')) 来初始化 使用的话就比较简单,直接将官方实例封装一个为方法,在mounted中调用即可。 |
二、 echarts2.0(官网: http://echarts.baidu.com/echarts2/)
[crayon-663479a6[……]
CentOS 安装 SS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
一、安装 wget –no-check-certificate https://raw.githubusercontent.com/teddysun/shadowsocks_install/master/shadowsocks.sh chmod +x shadowsocks.sh ./shadowsocks.sh 2>&1 | tee shadowsocks.log 二、输入密码 Please enter password for shadowsocks-python (Default password: teddysun.com): input your password 三、输入端口 Please enter a port for shadowsocks-python [1-65535] (Default port: 8989):input your port 四、 这一步会给出一个列表,输入列表项前面的数字来选择一个加密方法 Which cipher you'd select(Default: aes-256-gcm): input a number 五、安装成功 Congratulations, Shadowsocks-python server install completed! Your Server IP : your server ip Your Server Port : your port Your Password : your password Your Encryption Method:your encryption method Welcome to visit:https://teddysun.com/342.html Enjoy it! |
接下来下载 shadowsocks客户端,服务地址、端口、密码、加密方式填好就可以用了。
1 2 3 4 5 6 7 8 9 10 11 |
六、卸载 ./shadowsocks.sh uninstall 七、ShadowSocks常用命令 后台启动: ssserver -c /etc/shadowsocks.json -d start 后台停止: ssserver -c /etc/shadowsocks.json -d stop 启动:/etc/init.d/shadowsocks start 停止:/etc/init.d/shadowsocks stop 重启:/etc/init.d/shadowsocks restart 状态:/etc/init.d/shadowsocks status |
NodeJS + PhantomJS 前端自动化资源监控
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
前言:最近做前端资源监控,看了很多例子,没有达到想要的效果。首先的槽点是PhantomJS的官方文档,真鸡肋,其次是网上的例子,多数是介绍PhantomJS的用法,而并没有介绍怎么完整的去实现,跟官方文档好像也没啥区别...... 一、实现了什么? 本文只做一个简单的例子,获取网址加载时间,旨在实现一种思路,而不是很复杂的功能。 主要流程: 前端在页面加载时调用node接口 -> 将URL返回给接口 -> node获取url,然后通过子进程(child_process)启动系统命令 -> 启动PhantomJS-> PhantomJS打开url指定的网页,计算加载时间 -> 返回给node接口 -> 接口处理数据 -> 入库 二、主要实现 1、前端获取url let param = {'url': window.location.protocol + '//' + window.location.host}; 将url作为参数传递给接口。 2、NodeJS获取前端传递过来的url并启动phantomjs打开url,数据获取并处理 本文用的是sails框架。 首先是写models定义字段:ResourceMonitor.js module.exports = { connection: '数据库名', tableName: '表名', autoCreatedAt: true, autoUpdatedAt: true, attributes: { id: { type: 'integer', primaryKey: true, autoIncrement: true }, webAddress: { type: 'string' }, loadingTime: { type: 'string' } } } 然后写服务: resourceMonitorService.js module.exports = { async create(resourceMonitor){ try { try { if (resourceMonitor.id) { let oldResourceMonitor = await ResourceMonitor.findOne({id: resourceMonitor.id}); Object.assign(oldResourceMonitor, resourceMonitor); oldResourceMonitor.save(function (err) { if (err) throw err; return oldResourceMonitor; }) } else { return ResourceMonitor.create(resourceMonitor); } } catch (err) { throw err; } } catch (err) { throw err; } } } 接着是controller: resourceMonitorController.js const Cmd = require('cmd') module.exports = { async create(req, res){ try { let url = req.body['url'] //启动phantomJS let resource = await Cmd.resourceMonitorPhantom(url); if (!resource) return; //正则去除空格换行符回车符 resource = resource.replace(/[\s\n\r]+/g, "") //正则匹配'total:'和'ms'之间的所有非空白内容,并在返回结果后面加上'ms' let loadingTime = resource.match(/total:(\S*)ms/)[1] + ' ms'; //正则匹配'webAddress:'和'total:'之间的所有非空白内容 let webAddress = resource.match(/webAddress:(\S*)total:/)[1]; let resourceMonitor = {webAddress, loadingTime} if (!resourceMonitor) { sails.log.error("参数异常 " + JSON.stringify(resourceMonitor)) return res.send({code: -1, msg: "参数异常"}) } resourceMonitorService.create(resourceMonitor).then(function (data) { return res.send({code: 1, msg: "success", data: data}) }).catch(function (err) { sails.log.error("create resourceMonitor err" + err) return res.send({code: -1, msg: "get resourceMonitor list err"}) }) } catch (err) { sails.log.error("create resourceMonitor failure" + err) return res.send({code: -1, msg: "create resourceMonitor failure"}) } } } NodeJS命令行启动PhantonJS的方法:cmd.js //用的是node子进程中的execSync同步方法,可以等phantomjs处理完数据返回以后才执行接下来的内容 let execSync = require('child_process').execSync; module.exports = { async resourceMonitorPhantom(url){ try { let resourceMonitorCmd = `phantomjs ./phantom/resourceMonitorPhantom.js ${url}`; //由于phantomjs返回等数据是二进制流buffer,所以处理称字符串 let resourceMonitorOut = await execSync(resourceMonitorCmd).toString(); return resourceMonitorOut; } catch (err) { throw err; } } } PhantomJS获取资源加载时间:resourceMonitorPhantom.js var page = require('webpage').create(); var system = require('system'); var address; if (system.args.length === 1) { console.log(system.args) phantom.exit(); } else { var t = Date.now(); address = system.args[1]; page.open(address, function (status) { if (status !== 'success') { console.log('fail to load the address'); } else { t = Date.now() - t; console.log('webAddress:' + address + 'total:' + t + 'ms'); } phantom.exit(); }); } 三、涉及的框架及运行环境 1、NodeJS Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world. Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。 Node.js 的包管理器 npm,是全球最大的开源库生态系统。 官网:https://nodejs.org/ 2、Sails Sails.js (or Sails) is a Model-View-Controller (MVC) web application framework developed atop the Node.js environment, released as free and open-source software under the MIT License. It is designed to make it easy to build custom, enterprise-grade Node.js web applications and APIs. Emulating the MVC architecture of other frameworks, like Ruby on Rails it offers similar pattern and familiarity, reducing the cognitive burden when switching between other frameworks/languages. Sails.js (or Sails)是一个开发的模型-视图-控制器(MVC)web应用程序框架的节点。js的环境,在MIT许可下免费和开源软件的发布。它的目的是使它容易构建定制的,企业级节点。js web应用程序和api。效仿其他框架的MVC架构,像Ruby on Rails提供了类似的模式和熟悉,减少认知负担当切换其他框架/语言。 官网:http://sailsjs.com/ 3、 PhantomJS PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG. PhantomJS,脚本化的WebKit内核的无头浏览器,支持各种web标准:DOM处理CSS选择器,JSON,Canvas,SVG。 简单的说,就是一个没有界面的webkit内核浏览器,只能在命令行下使用。可以做很多事,比如:生成网页截图、抓去网页数据、获取网络资源加载时间等。 官网:http://phantomjs.org/ |