VueJS 爬坑笔记

Mark神塞,90后技术极客直男,通晓前端技术,在他的推荐下,我接触了vue。 起初吸引我的是vue的小巧轻快,以及优雅的数据绑定操作,但随着学习的深入,发现vue完全是有别于以往前端开发的架构和流程,作为十几年的老司机,耳目一新,技术的演进真是令人兴奋。 但目前vue国内文档和生态社区尚不完整,有问题基本搜索不到。好在QQ群有近500多名先行者,很多问题在不断地虚心讨教后基本可以得到解决。

爬坑笔记其实不算笔记,一切尽在代码中吧:

Repo: https://github.com/silverd/staylife

Demo: http://m.staylife.cn

项目采用 vue-cli 的 webpack 标准模板构建,使用到的主要社区组件有:

  • vue-router
  • vue-resource
  • vue-infinite-scroll
  • vux (weui)
  • sass-loader
  • vue-lazyload
  • vue-spinner (很赞的 loading 组件)
  • locutus (经典的 phpjs.org 的一些函数库)

几个可以特别指出的点:

  • 计算属性的奥秘 computed http://vuejs.org.cn/guide/reactivity.html#计算属性的奥秘
  • 组件 keep-alive 的使用
  • 组件 attach/ready 的执行时机
  • AJAX POST CORS 跨域(withCredentials)
  • 全局 Preloader 的实现
  • 过渡动画 transition 的使用
  • webpack 的加载路径(参见 webpack.base.conf 中的 resolve)
  • 让文本框聚焦需要使用 v-el 属性
  • vm.$nextTick 的使用 http://vuejs.org.cn/guide/reactivity.html#异步更新队列
  • 微信 iOS 修改网页标题的黑科技
  • 微信 wx.config 代码位置
  • 微信安卓版不能正确执行字符串的 includes/startWith 等 ES6 的新方法

NPM 相关

package.json 中 dependencies 和 devDependencies 区别

  • dependencies 正常运行该包(npm build)时所需要的依赖项,通过 npm install --production 安装
  • devDependencies 开发的时候需要的依赖项,比如一些单元测试的包

默认会安装两种依赖,如果你只是单纯的使用这个包而不需要进行一些改动测试之类的,可以使用

npm install

只安装dependencies而不安装devDependencies。

npm install --production

如果你是通过以下命令进行安装

npm install XXX

那么只会安装 dependencies,如果想要安装 devDependencies,需要输入

npm install XXX --dev

-save-save-dev 可以省掉你手动修改 package.json 文件的步骤。

  • npm install XXX -save 自动把模块和版本号添加到dependencies部分
  • npm install XXX -save-dev 自动把模块和版本号添加到devdependencies部分

《TalkingCoder@Vue+Webpack直播内容分享》的后续补充:

Vue

  • Vue.config.debug(在调试模式中,打印所有警告的栈追踪,所有的锚节点以注释节点显示在 DOM 中)
  • 异步组件 component resolve http://vuejs.org.cn/guide/components.html#异步组件
  • 双向绑定的原理 http://vuejs.org.cn/guide/reactivity.html#如何追踪变化
  • vm.$emit(父组件向指定的一个子组件触发事件)http://vuejs.org.cn/api/#vm-emit
  • this.$refs(在父组件上注册一个子组件的索引,便于直接访问)
  • this.$els(相当于 document.getElementById,获取页面上指定的DOM元素,例如修改 innerHTML 或光标自动聚焦等场景)
  • slot 插槽的作用
  • 循环里删除指定一行的小技巧: this.itemList.$remove(item)
  • 路由 hashbang 和 HTML5 history 模式的各自使用场景区别和优劣势
  • 组件里引入一个 CSS 的几种写法以及区别:
    • <style> @import 'a.css' </style>
    • <script> import 'a.css' </script>
    • <style src="a.css"></style>
  • css scoped 的表现
  • 组件里 ready 和 attached 的区别(组件的生命周期 beforeDestroy)
  • 自己开发的组件,如何发布到 npmjs?

Webpack

  • Webpack 和 gulp/grunt 的区别(gulp 只做合并压缩的事,webpack 除了做 gulp 的事外,还会做代码抽离、模块化、依赖管理)
  • package.json 中 dependencies 和 devDependencies 的区别
  • config.devtool = ‘#source-map’ 的作用和优化
  • 优化 webpack 打包后的文件大小
  • 热刷新 hot-reload 的原理和注意点(只有子组件可以热刷,css文件无法热刷)

Charlse 抓包使用心得

最常见的功能就不累述了,这里记录几个有价值的功能。

电脑浏览器抓包 HTTPS

http://www.charlesproxy.com/ssl.zip 下载CA证书文件。 双击其中的.crt文件,选择“总是信任”,从钥匙串访问中即可看到添加成功的证书。

然后 Charles -> Proxy -> Mac OS X Proxy 将 Charles 设置成系统代理。

移动设备抓包 HTTPS

  1. 将手机代理设置为电脑
  2. 在手机上安装导入证书
    • 电脑 Charles ->Help -> SSL Proxying ->Install Charles Root Certifate on a Mobile Device or Remote Browser
    • 手机 Safari 打开 http://charlesproxy.com/getssl 安装证书。
  3. 电脑 Charles -> Proxy -> SSL Proxy Settings 增加需拦截的域名:443。
  4. 如发现 SSL 解密失败,那需检查一下手机的信任设置:
    • 设置->通用->关于本机->证书信任设置,开启对 Charles Proxy Custom Root Certification 的信任。
  5. 设置需要捕获的域名 Charles -> Proxy -> Proxy Settings -> SSL -> Enable SSL Proxying,在下方 Locations 区域添加要抓取的域名和端口 443

过滤网络请求

方法1:在主界面的中部的 Filter 栏中填入过滤出来的关键字(模糊匹配) 方法2:Charles -> Proxy -> Recording Settings -> Include 栏,选择添加一个项目,然后填入需要监控的协议,主机地址,端口号

通常情况下,方法1做一些临时性的封包过滤,方法2做一些经常性的封包过滤。

重复发包

通常情况下,我们使用方法1做一些临时性的封包过滤,使用方法2做一些经常性的封包过滤。

在请求上右键可以选择 Repeat(发包一次) / Repeat Advanced(发包多次),这个功能用来测试短信轰炸漏洞很方便。

修改网络请求内容

在请求上右键可以选择 Edit,即可创建一个可编辑的网络请求

修改网络响应内容

在一个 JS/CSS 请求上右键选择 Map Local,用本地的文件映射替代。

功能类似 Fiddler 的 AutoResponder,可用于线上调试JS/CSS代码

模拟慢速网络 Throttle

模拟慢速网络或者高延迟的网络,以测试在移动网络下,应用的表现是否正常。

Charles -> Proxy -> Throttle Setting,勾选上 Enable Throttling,并且可设置 Throttle Preset 的类型

如果只想模拟指定网站的慢速网络,可以再勾选上图中的 Only for selected hosts 项,然后在对话框的下半部分设置中增加指定的 hosts 项即可。

参考文章:

Mac 搭建开发环境(三)Nginx/PHP-FPM

安装 Nginx+PHP-FPM

brew install nginx --with-http2
brew install php@7.4

Nginx 配置

默认的 DocumentRoot 为 /usr/local/var/www/ => /usr/local/opt/nginx/html/

默认是监听的是 localhost:8080 端口,可以在 nginx.conf 中修改。

# 默认的配置文件位置
/usr/local/etc/nginx/nginx.conf

# 快捷方式(个人喜好)
ln -s /usr/local/etc/nginx/ ~/nginx-conf
ln -s /usr/local/etc/nginx/servers ~/nginx-conf/vhost

修改 vi ~/nginx-conf/nginx.conf 超时时间及缓冲区等配置,在 http {} 区块增加以下内容:

server_names_hash_bucket_size 128;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 50m;

fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 256k;

新建 vi ~/nginx-conf/pathinfo.conf

fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
try_files $fastcgi_script_name =404;

新建虚拟主机(完整版)vi ~/nginx-conf/vhost/staylife.conf

server {

    listen 80;
    server_name local.wp.staylife.cn local.api.staylife.cn;
    root /Users/silverd/home/wwwroot/staylife_server/app/web;

    index index.html index.htm index.php;
    autoindex on;

    location ~ [^/]\.php(/|$) {
        fastcgi_pass  127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi.conf;
        include pathinfo.conf;
    }

    location / {
        if (!-e $request_filename) {
            rewrite ^/(.*)$ /index.php/$1 last;
        }
    }

}

但我的做法是抽出了几个配置文件:

vi ~/nginx-conf/php.conf

index index.html index.htm index.php;
autoindex on;

location ~ [^/]\.php(/|$) {
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    include fastcgi.conf;
    include pathinfo.conf;
}

vi ~/nginx-conf/php-yaf.conf

include php.conf;

location / {
    if (!-e $request_filename) {
        rewrite ^/(.*)$ /index.php/$1 last;
    }
}

vi ~/nginx-conf/php-laravel.conf

include php.conf;

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

vi ~/nginx-conf/php-yii.conf

include php.conf;

location / {
    try_files $uri $uri/ /index.php$is_args$args;
}

然后虚拟主机 vhost/*.conf 里都 include php-yaf.conf,于是 staylife.conf 最终变成了:

server {
    listen 80;
    server_name local.api.staylife.cn;
    root /Users/silverd/home/wwwroot/staylife/app/web;
    include php-yaf.conf;
}

Nginx 进程管理

# 如果想要 Nginx 开机自启动,则必须以 root:wheel 权限运行
# Linux 系统非 root 用户禁用 1024 以下的端口
sudo chown root:wheel /usr/local/bin/nginx
sudo chmod u+s /usr/local/bin/nginx

# 启动
sudo nginx

# 重启、停止等
sudo nginx -s reload|reopen|stop|quit

# 设置 Nginx 开机启动
sudo ln -sfv /usr/local/opt/nginx/*.plist /Library/LaunchDaemons
sudo chown root:wheel /Library/LaunchDaemons/homebrew.mxcl.nginx.plist
sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.nginx.plist

PHP-FPM 进程管理

# 配置文件
/usr/local/etc/php/7.4/php-fpm.conf

# 如果想要 php-fpm 开机自启动,则必须以 root:wheel 权限运行
sudo chown root:wheel /usr/local/sbin/php-fpm
sudo chmod u+s /usr/local/sbin/php-fpm

# 其他方法:启动 php-fpm
sudo /usr/local/sbin/php-fpm --daemonize -c /usr/local/etc/php/7.4/php.ini -y /usr/local/etc/php/7.4/php-fpm.conf

# 其他方法:关闭 php-fpm
sudo kill -INT `cat /usr/local/var/run/php-fpm.pid`

# 其他方法:重启 php-fpm
sudo kill -USR2 `cat /usr/local/var/run/php-fpm.pid`

# 设置 php-fpm 开机启动
sudo ln -sfv /usr/local/opt/php@7.4/homebrew.mxcl.php@7.4.plist /Library/LaunchDaemons
sudo chown root:wheel /Library/LaunchDaemons/homebrew.mxcl.php.plist
sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.php.plist

或者直接设置命令别名 vi ~/.zshrc,加入:

alias nginx.start="sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.nginx.plist"
alias nginx.stop="sudo launchctl unload -w /Library/LaunchDaemons/homebrew.mxcl.nginx.plist"
alias nginx.restart='nginx.stop && nginx.start'

alias php.start="sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.php.plist"
alias php.stop="sudo launchctl unload -w /Library/LaunchDaemons/homebrew.mxcl.php.plist"
alias php.restart='php.stop && php.start'

source ~/.zshrc

FAQ

如何让 http://localhost 支持 PHP?

修改 nginx.conf,并打开 server {} 下被注释的 location ~.php$ 即可。

如果访问 http://localhost/index.php 出现 File not found 那么修改 nginx.conf

查找:fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
替换为:fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

Nginx 无法启动

使用 nginx -t 检测配置文件是否有误,如果提示了:

nginx: [alert] could not open error log file: open() "/usr/local/var/log/nginx/error.log" failed (13: Permission denied)
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
2020/04/20 14:37:55 [emerg] 61477#0: open() "/usr/local/var/run/nginx.pid" failed (13: Permission denied)
nginx: configuration file /usr/local/etc/nginx/nginx.conf test failed

那必须执行修改权限:

sudo chown root:wheel /usr/local/bin/nginx
sudo chmod u+s /usr/local/bin/nginx

网页报 500 服务器内部错误

修改 /usr/local/etc/php.ini,打开并记录错误日志 error_log=/Users/silverd/home/wwwlogs/php_error.log

参考文章

Mac 搭建开发环境(二)常用软件

Finder 中显示完整路径

defaults write com.apple.finder _FXShowPosixPathInTitle -bool TRUE;killall Finder

关于 .DS_store 文件

说明:.DS_Store 文件是 MacOS 保存文件夹的自定义属性的隐藏文件,如文件的图标位置或背景色,相当于 Windows 的 desktop.ini。

# 禁止 .DS_store 生成
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool TRUE

# 开启 .DS_store 生成
defaults delete com.apple.desktopservices DSDontWriteNetworkStores

Node.js+Npm

建议用 nvm 来管理和安装 node 版本,查看使用说明nvm 和 n 的区别和原理

如果之前曾经用官网 pkg 包安装过 node,则需要先删除:

# 查看已安装在全局模块,以便重装
npm ls -g --depth=0

# 删除 node
sudo rm /usr/local/bin/node

# 删除全局 node_modules 目录
sudo rm -rf /usr/local/lib/node_modules

# 删除全局 node 模块注册的软链
cd  /usr/local/bin && ls -l | grep "../lib/node_modules/" | awk '{print $9}'| xargs rm

清理完毕后,开始通过 nvm 来安装 node:

# 安装 nvm
# 如想安装最新版本的 nvm 可以去 https://github.com/creationix/nvm
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash

# 安装最新稳定版 node
nvm install stable

# 安装指定版本 node
nvm install 6.9.1

# 切换到指定 node 版本
nvm use 7

另外可以用 nrm 来切换 npm 源,查看使用说明

# 安装 nrm
sudo npm install -g nrm

# 列出可选的源
nrm ls

# 测试所有源的响应时间
nrm test

# 切换到指定源
nrm use taobao

提示:如果某个项目需要单独指定 node 版本,可以在项目根目录下新建一个 .nvmrc 文件来特殊标明:

cd staylife_frontend/mobile
echo 4 > .nvmrc
nvm use
node -v

SublimeText3

下载地址:http://www.sublimetext.com/3

安装常用插件:

  • PackageControl
  • Alignment
  • MarkdownHighlighting
  • Sass
  • Less
  • Vue Syntax Highlight
  • DocBlockr
  • ColorsSublime 代码高亮主题管理插件,安装成功后需要照着文档配置两个地方
  • Material Theme 非常棒的编辑器主题
  • Blade Snippets Blade 模板自动补全
  • Laravel Blade Hightlighter Blade 语法高亮支持
  • SyncedSideBar 自动在左边文件夹树中定位当前文件
  • BracketHighlighter 结尾处高亮
  • EditorConfig .editorconfig 编码格式化支持
  • Emmet 快速编码
  • SideBarEnhancements 文件夹栏右键菜单增强
  • AdvancedNewFile 快速创建新文件
  • GitGutter 标记代码中做的编辑
  • Laravel 5 Artisan Artisan 命令行调用
  • Laravel 5 Snippets 代码片段
  • SublimeLinter + SublimeLinterPHP 代码检测

想在命令行使用 Sublime?

ln -s /Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl /usr/local/bin/subl
ln -s /usr/local/bin/subl /usr/local/bin/sublime

Zsh/OhMyZsh

brew install zsh
wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh

echo 'export PATH="/usr/local/sbin:$PATH"' >> ~/.zshrc
source ~/.zshrc

Vi/Vim

# 安装 monokai 主题
1.下载 Monokai.vim (https://github.com/sickill/vim-monokai) 保存到 ~/.vim/colors 下;
2.编辑 ~/.vimrc 文件,添加 syntax enable、colorscheme Monokai 两行,例如:

    syntax enable
    colorscheme Monokai

    set encoding=utf-8
    set fileencoding=utf-8
    set fileencodings=ucs-bom,utf-8,chinese,cp936
    set guifont=Consolas:h15
    language messages zh_CN.utf-8
    set autoindent
    set smartindent
    set tabstop=4
    set autochdir
    set shiftwidth=4
    set foldmethod=manual
    set nocompatible
    set nobackup

CharlseProxy

http://www.charlesproxy.com/download/

如何抓取 https?

# 设置手机代理、安装证书(依次点击可查看当前电脑IP、端口、证书地址)
1、Charles ->Help -> SSL Proxying ->Install Charles Root Certifate on a Mobile Device or Remote Browser
2、用手机浏览器(Safari)打开并安装上面窗口提示的证书,例如:
    http://www.charlesproxy.com/getssl

# 设置需要捕获的域名
4、Charles -> Proxy -> Proxy Settings -> SSL -> Enable SSL Proxying,在下方 Locations 区域添加要抓取的域名和端口443

Wine

# XQuartz >= 2.7.7
brew install Caskroom/cask/xquartz

# 安转 wine
brew install wine

# 或者去官网下载
https://dl.winehq.org/wine-builds/macosx/download.html

# 开始安装
wine heidisql-installer.exe

# 启动程序
wine /User/....exe

Git

brew install git
git config --global branch.autosetuprebase always
git config --global core.ignorecase false
git config --global core.autocrlf input
git config --global core.safecrlf true
git config --global credential.helper store
git config --global core.excludesfile ~/.gitignore_global
git config --global push.default simple

# 设置提交者
git config --global user.name "silverd"
git config --global user.email "silverd29@gmail.com"

SourceTree

https://www.sourcetreeapp.com/download/

iTerm2

http://www.iterm2.com/downloads.html

# 安装主题(Solarized Dark Higher Contrast 不错)
http://www.iterm2.com/colorgallery

Scroll Reverser

http://pilotmoon.com/scrollreverser/

ShadowsocksX

# ShadowsocksX-2.6.3.dmg
https://github.com/shadowsocks/shadowsocks-iOS/releases

SecureCRT

# v7.3.7 下载地址
http://macabc.com/detail.htm?app_id=24

# 正常安装

# 破解方法1. 下载破解文件 securecrt_mac_crack.pl
地址1:http://yun.baidu.com/share/link?shareid=297986172&uk=18145526
地址2:https://raw.githubusercontent.com/silverd/silverd.github.io/master/res/attach/securecrt_mac_crack.pl

# 破解方法2. 在终端执行命令,会返回一组序列号信息,然后打开 SecureCRT 手动依次输入这些信息就可
sudo perl securecrt_mac_crack.pl /Applications/SecureCRT.app/Contents/MacOS/SecureCRT

# 破解方法原文
http://bbs.feng.com/read-htm-tid-6939481.html
# 下载链接(直接就是破解版 v11.1.8)
http://www.waitsun.com/navicat-premium-11-1-11.html

Alfred+Dash

# Alfred3 破解版
http://www.sdifenzhou.com/alfred3.html

# Dash
http://scriptfans.iteye.com/blog/1543219

# Dash 集成 Alfred
Dash -> Preference -> Integration -> Alfred Import

Genymotion+VitualBox

https://www.virtualbox.org/wiki/Downloads
https://www.genymotion.com/download/

增加 ssh-copy-id 命令(MacOS 不自带)

# 仓库原地址:https://github.com/beautifulcode/ssh-copy-id-for-OSX
curl -L https://raw.githubusercontent.com/beautifulcode/ssh-copy-id-for-OSX/master/install.sh | sh

# 用法示例
ssh-copy-id -i ~/.ssh/dev@morecruit.pub root@m.hicrew.cn

Mac 搭建开发环境(一)LAMP

安装 homebrew

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

切换 Homebrew 中国源(清华大学)

参见:https://mirror.tuna.tsinghua.edu.cn/help/homebrew/

git -C "$(brew --repo)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git
git -C "$(brew --repo homebrew/core)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git
git -C "$(brew --repo homebrew/cask)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-cask.git
git -C "$(brew --repo homebrew/cask-fonts)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-cask-fonts.git
git -C "$(brew --repo homebrew/cask-drivers)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-cask-drivers.git

# 更换后测试工作是否正常
brew update

Command Line Tools

方法1. brew doctor 后根据提示自动安装
方法2. xcode-select --install
方法3. 在 AppStore 里安装最新版 Xcode

准备工作

brew install wget
brew install libevent
brew link libevent
brew install autoconf
brew install pkg-config
brew install libmemcached

# 如果出现连接不上,可尝试修改DNS解析:
sudo vi /etc/resolev.conf
nameserver 114.114.114.114
nameserver 8.8.8.8

安装基础服务

brew install homebrew/apache/httpd24
brew install homebrew/php/php71 --with-apache
brew install memcached
brew install redis
brew install mongodb

安装 PHP7 PECL 扩展(–HEAD 表示最新但非稳定版)

brew install homebrew/php/php71-memcached
brew install homebrew/php/php71-redis
brew install homebrew/php/php71-mongodb
brew install homebrew/php/php71-xxtea
brew install homebrew/php/php71-yaf
brew install homebrew/php/php71-swoole
brew install homebrew/php/php71-mcrypt

安装 PHP Composer 包管理器

brew install homebrew/php/composer
composer self-update

# 启用 Packagist 中国镜像
composer config -g repo.packagist composer https://packagist.phpcomposer.com

可选安装 PHP7-PECL-YAF 扩展

homwbrew 里已可以安装 php71-yaf,但版本可能不是最新。可以跳过本步。

wget http://pecl.php.net/get/yaf-3.0.4.tgz
tar zxvf yaf-3.0.4.tgz
cd yaf-3.0.4

phpize
./configure
make && make install
echo 'extension=yaf.so' > '/usr/local/etc/php/7.1/conf.d/ext-yaf.ini'
cd ..
rm -rf yaf-3.0.4 yaf-3.0.4.tgz package.xml

查看 php -v 可能会遇到 memcached 依赖问题

PHP Deprecated: PHP Startup: memcached.sess_lock_wait and memcached.sess_lock_max_wait are deprecated. Please update ...

按照所述修改 `/usr/local/etc/php/7.1/conf.d/ext-memcached.ini`

移除以下两句
memcached.sess_lock_wait = 150000
memcached.sess_lock_max_wait = 0

更换成新版的写法
memcached.sess_lock_wait_min = 0;
memcached.sess_lock_wait_max = 0;
memcached.sess_lock_retries = 0;

开启 PHP 解析短标签

修改 `/usr/local/etc/php/7.1/php.ini` 设置 short_open_tag = On

启动、重启、停止 Apache

sudo apachectl start
sudo apachectl stop
sudo apachectl restart

通过 `httpd -V` 也可以查看当前 Apache 的版本以及 httpd.conf 所在路径 (SERVER_CONFIG_FILE)
/usr/local/etc/apache2/2.4/httpd.conf

Apache 修改 /usr/local/etc/apache2/2.4/httpd.conf

# 如果访问 localhost 出现 403 Forbidden?
找 `Require all denied` 替换成 `Require all granted`

# 开启 mod_rewrite 模块
取消注释 `LoadModule rewrite_module libexec/apache2/mod_rewrite.so`

# 如果是 PHP7,还需修改 Mac 自带 apache 的 PHP 模块,
搜索 `LoadModule php5_module libexec/apache2/libphp5.so`
替换 `LoadModule php7_module /usr/local/Cellar/php71/7.1.*/libexec/apache2/libphp7.so`

# 开启引入虚拟主机
取消注释 `Include /usr/local/etc/apache2/2.4/extra/httpd-vhosts.conf`

# 在文件最底部增加:
<IfModule php7_module>
    AddType application/x-httpd-php .php
    AddType application/x-httpd-php-source .phps
    <IfModule dir_module>
        DirectoryIndex index.html index.php
    </IfModule>
</IfModule>

如何新建一个 Apache vhost?

sudo vi /usr/local/etc/apache2/2.4/extra/httpd-vhosts.conf

<VirtualHost *:80>
    ServerName local.api.hicrew.cn
    ServerAlias local.m.hicrew.cn
    DocumentRoot "/Users/silverd/home/wwwroot/hicrew/app/web"
    <Directory "/Users/silverd/home/wwwroot/hicrew/app/web">
        Options Indexes FollowSymLinks
        Require all granted
        AllowOverride All
        <IfModule mod_rewrite.c>
            RewriteEngine On
            RewriteCond %{REQUEST_FILENAME} !-f
            RewriteCond %{REQUEST_FILENAME} !-d
            RewriteRule ^(.*)$ /index.php/$1 [L]
        </IfModule>
    </Directory>
</VirtualHost>

特别注意:

DocumentRoot 必须是绝对路径。不能简写为 ~/home/wwwroot/…,否则会报 404 Not Found

因为 DocumentRoot 是相对 ServerRoot 而言的,httpd.conf 中 ServerRoot 是 /Users

MySQL 安装和管理

# 第1步:安装
brew install mysql

# 第2步:启动(会以当前登录身份启动)
mysql.server start

# 第3步:设置密码(然后按提示操作)
mysql_secure_installation

# 第4步:停止
mysql.server stop

# 将 MySQL Server 设为开机启动(以 root 身份启动)
sudo ln -sfv /usr/local/opt/mysql/*.plist /Library/LaunchDaemons
sudo chown root:wheel /Library/LaunchDaemons/homebrew.mxcl.mysql.plist
sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.mysql.plist

# 停止 MySQL Server
sudo launchctl unload -w /Library/LaunchDaemons/homebrew.mxcl.mysql.plist

附录:用 launchctl 来管理服务

官方不推荐用 brew services 方式管理服务(以后可能被淘汰),那么可以用以下方法:

# 将 Redis Server 设为开机启动
sudo ln -sfv /usr/local/opt/redis/*.plist /Library/LaunchDaemons
sudo chown root:wheel /Library/LaunchDaemons/homebrew.mxcl.redis.plist
sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.redis.plist

# 停止 Redis Server
sudo launchctl unload -w /Library/LaunchDaemons/homebrew.mxcl.redis.plist

# 将 Memcache Server 设为开机启动
sudo ln -sfv /usr/local/opt/memcached/*.plist /Library/LaunchDaemons
sudo chown root:wheel /Library/LaunchDaemons/homebrew.mxcl.memcached.plist
sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.memcached.plist

# 停止 Memcache Server
sudo launchctl unload -w /Library/LaunchDaemons/homebrew.mxcl.memcached.plist

特别注意:当 Memcached 以 root 身份启动时,必须带上 -u 参数,需修改 plist

sudo sed -i '' \
    -e 's#<string>-l</string>#<string>-u</string>#g' \
    -e 's#<string>localhost</string>#<string>root</string>#g' \
    /Library/LaunchDaemons/homebrew.mxcl.memcached.plist

修改后的 plist 全文如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>homebrew.mxcl.memcached</string>
    <key>KeepAlive</key>
    <true/>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/opt/memcached/bin/memcached</string>
        <string>-u</string>
        <string>root</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>Debug</key>
    <true/>
    <key>WorkingDirectory</key>
    <string>/usr/local</string>
    <key>StandardErrorPath</key>
    <string>/usr/local/var/log/memcached.log</string>
    <key>StandardOutPath</key>
    <string>/usr/local/var/log/memcached.log</string>
</dict>
</plist>

或者直接设置命令别名 vi ~/.zshrc,加入:

alias mysql.start="sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.mysql.plist"
alias mysql.stop="sudo launchctl unload -w /Library/LaunchDaemons/homebrew.mxcl.mysql.plist"
alias mysql.restart='mysql.stop && mysql.start'

alias redis.start="sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.redis.plist"
alias redis.stop="sudo launchctl unload -w /Library/LaunchDaemons/homebrew.mxcl.redis.plist"
alias redis.restart='redis.stop && redis.start'

alias memcached.start="sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.memcached.plist"
alias memcached.stop="sudo launchctl unload -w /Library/LaunchDaemons/homebrew.mxcl.memcached.plist"
alias memcached.restart='memcached.stop && memcached.start'

source ~/.zshrc

附录:homebrew 其他技巧

# 诊断 brew
brew doctor

# 查看配置和版本
brew config

# 更新 brew 源
brew update

# 升级软件
brew upgrade

# 卸载软件
brew uninstall wget

# 使用 brew 第三方安装源
brew tap phinze/homebrew-cask
brew install brew-cask

# 然后像 brew 一样来安装软件
brew cask install google-chrome

# 查看 homebrew cask 已支持软件列表
https://github.com/phinze/homebrew-cask/tree/master/Casks

# 卸载软件
brew cask uninstall google-chrome

2016.10.25 补充说明

自 MacOS Sierra 系统发布后,homebrew 里的 php71 安装时默认不会编译 Apache 的 libphp7.so 模块,务必加上 --with-apache 参数

brew install homebrew/php/php71 --with-apache

如果通过 homebrew 升级了 Apache2.4(Mac虽然自带 Apache,但有些库版本较旧,可通过 /usr/sbin/httpd -v 可查看自带的 Apache 版本)

那么请移步:Mac 通过 brew 安装 Apache2.4

2016.11.01 一键安装脚本

本司的全栈小王子陈问鱼同学把以上各步骤写成了一个自动脚本,无人值守、省时省力,以后再也不用一步步复制粘贴啦~

可以通过直接在命令行运行 cURL:

curl -o- https://raw.githubusercontent.com/silverd/silverd.github.io/master/res/attach/install_mac_dev_env.sh | sh

或者 Wget:

wget -qO- https://raw.githubusercontent.com/silverd/silverd.github.io/master/res/attach/install_mac_dev_env.sh | sh

Linux 学习笔记:输出日志 >/dev/null 2>&1

  1. 标准输入 stdin 文件描述符为 0
  2. 标准输出 stdout 文件描述符为 1
  3. 标准错误 stderr 文件描述符为 2
  4. /dev/null 表示空设备,相当于垃圾桶

2>1 与 2>&1 的区别

  • 2>1 把标准错误 stderr 重定向到文件 1 中
  • 2>&1 把标准错误 stderr 重定向到标准输出 stdout

各种举例说明

假设有脚本 test.sh,内容如下:

t 是一个不存在的命令,执行脚本进行下面测试。

# cat test.sh
t
date

标准输出重定向到 log,错误信息输出到终端上,如下:

# ./test.sh > log
./test.sh: line 1: t: command not found

# cat log
Thu Mar 23 22:53:02 CST 2016

删除 log 文件,重新执行,这次是把标准输出定向到 log,错误信息定向到文件 1

# ./test.sh > log 2>1
# cat log
Thu Mar 23 22:56:20 CST 2016
# cat 1
./test.sh: line 1: t: command not found

把标准输出重定向到 log 文件,把标准错误重定向到标准输出

# ./test.sh > log 2>&1
#
# cat log
./test.sh: line 1: t: command not found
Thu Mar 23 22:58:54 CST 2016

把错误信息重定向到空设备

# ./test.sh 2>/dev/null
Thu Mar 23 23:01:07 CST 2016

把标准输出重定向到空设备

# ./test.sh >/dev/null
./test.sh: line 1: t: command not found

把标准输出和标准错误全重定向到空设备

#./test.sh >/dev/null 2>&1