专注于WEB前端开发, 追求更好的用户体验, 更好的开发体验 (长沙前端QQ群:234746733)

工具

  • webpack

    / 分类: 工具 / No Comments

    因为杂事比较多, 很久没写blog了. 深知坚持写下去, 自己的收货也是很大的, 所以和同事打赌每周写一篇blog, 如果做不到就请喝coffee(每周一篇质量不能保证, 只能做到1个月1-2篇~).
    "时间挤一挤总会有的"这句话都听过, 但是做起来不一定那么容易. 可能很多人也经常抱怨自己没时间做某某事, 因为惰性, 一个想法过了1年/2年没有去做, 后面就荒废了.
    改变自己是最难的, 很多改变也是被逼出来的. 2016, 希望效率能更高, 能把零碎的时间也都利用好.

    webpack应该一年以前就研究了, 当时还准备有机会在w3cteach长沙分享的, 那时介绍react/webpack应该极少, 现在已经很多了.
    说了些题外话, 开始入正题了.

    webpack的作用

    总结为: 打包,优化,编译.
    打包: 就是可以把模块打包, 处理依赖, 用过requirejs应该很好理解.
    优化: 比如图片可以转成base64, 可以最大限度减少http请求.
    编译: 这个很重要, 如果一个旧项目, 页面引入了a.js...n.js, 还在思考用gulp/grunt用最普通的方式把*.js压缩合并到一起, 那么理解起来会有点痛苦, 也发现不了webpack的优势, 最好是先通过一个简单的demo或新项目去理解. 需要某个模块的时候, 只要放心大胆的require就好了(webpack里面任何的静态资源都可以当做模块), 最终代码成什么样子webpack已经替你处理好了.

    webpack的常用配置参数

    //webpack.config.js
    module.exports = {
        context: __dirname + '/src', // requre('a.js')的时候从哪个路径查找
        entry: { // 打包成2个文件index.js, about.js
            index: ['./a.js', './a.css', './b.js', './b.css'], // css和js打包到一起(一个js文件), 用<style>添加到页面
            about: ['./a.js', './a.css', './c.js', './c.css'],
        },
        output: { // 打包后的输出目录
            path: './build', // 打包后的文件路径
            publicPath: 'build/', // 打包文件内用到的URL路径, 比如背景图等(可以设成http的地址, 比如: http://cdn.my.com)
            filename: '[name].js' // 打包后生成文件的命名规则, 这里是: index.js, about.js
        },
        externals: { // 遇到require这些时, 不需要再编译. 适合那些常用的库, 已经在页面通过<script>引入了, 就无需都打包到一起了 
            jquery: 'jQuery',
        },
        module: {
            loaders: [
                { test: /\.css$/, loader: 'style-loader!css-loader' }, // 针对.css文件用2个加载器预处理(!号隔开多个加载器)
            ]
        },
    };
    

    加载模块

    // 1. 同步加载一个模块(像不像nodejs?)
    var a = require('./a.js');
    a.show();
    
    // 2. 异步按需加载模块(像不像requrejs?)
    require(['./a.js'], function(module){
        module.show();
        var c = require('./c.js').show(); // webpack的优化: 最终c.js会和a.js打包成一个模块
    });
    

    可以看到, 无论AMD/CMD标准的代码webpack都可以支持. 模块依赖/互相调用的问题, 轻松就解决了, 不需要自己开发或或引用第三方模块加载器了.

    上面提到, 任何资源都可以作为模块, 图片/html/json等, 都是可以require的, 只要配置好webpack配置的loaders里面的规则就OK了.

    优化打包

    什么时候css不打包成JS, 让css也打包成独立的css文件?
    打包后的文件名想用带哈希的文件名, 避免缓存?
    所有的页面都引用了common.js, lib.js, 希望最终打包的时候, 自动把公共的代码打包成一个独立的common.js?
    base64后, 图片的确减少了请求, 但是大图base64得到的字符串太长, 只希望小图片才转base64?
    这些都可以做到, 下面的PPT里面有写. 同时还有autoprefixer的介绍, scss/less/图片加载的例子, 通过css-sprite优化sprite.
    还有, debug的代码上线时, 不需要手动注释, 可以让webpack自动移除.

    旧项目如何改造

    AMD/CMD什么的还是要改造旧代码, 旧项目很多lib都是注册变量到window对象下面的, 怎么解?
    webpack提供Shim支持, 因为加载模块的逻辑都是loader来处理规则的, 所以imports,exports,expose这三个loader完全可以搞定旧lib.

    webpack-dev-server

    启动webpack-dev-server后, 本地调试代码时, 页面只需引入<script src="http://localhost:8080/webpack-dev-server.js"></script>, 在改版静态资源经过webpack编译好后, 页面会自动更新.

    和gulp结合使用

    webpack和gulp并不是敌人, 他们可以搭配使用, 只是我们的惯性思维, 还是停留在用gulp去做打包的动作. 当然单独用webpack基本大部分项目已经足够, 如果项目复杂, 任务较多, 或者需要使用不同的webpack实例, 那么他们结合起来用是没有任何问题的. gulp只负责好任务就OK了.

    links

    1. demo, 包括了webpack/gulp/css-sprite各自的例子以及组合使用的例子.
    2. webpack介绍PPT, 快一年了, 带批判性的看吧.
  • 自托管的git服务对比

    / 分类: 工具 / 4 Comments

    收集和对比了下一些自托管的git服务, 应该算比较全了; 同样在寻找比较好的方案的同学, 或许可以参考下, 少走一些弯路.

    收费

    • GitHub Enterprise: 按年付费,价格较贵(20人以内:$5000/每年),不提供源代码(只提供整套镜像:VMware的OVA镜像,和AWS的AMI镜像名),因为是一整套的镜像, 应该不能二次开发(stash没有这些限制).
    • Atlassian Stash: 语言:java, 按网上的评论应该是好于gitlab, 毕竟是收费的. 不需按年付费, 比Enterprise还是算便宜了(10人以内很便宜,只要$10).

    免费

    • gitlab: 语言:ruby, 应该免费的里面功能最完善的, 按官方文档安装容易卡住, 可以用这个一键安装包.
    • Gitorious: 也是ruby, 也有一键安装包, 评论基本都是安装/使用的体验比gitlab弱一些.
    • gitprep: 语言:Perl, 好像是个人开发的, 官网有demo可以看.
    • Gogs: 语言:Go, 感觉不错, 国人开发的, 更新较快(目前,没看到新建分支/pull-request功能).
    • gitbucket: 语言:Scala, 看界面和功能介绍貌似还不错.
    • Douban CODE: 语言:Python, github上的代码只提供一些基础功能(据说, 现在没人维护了, 有些可惜).

    Ps: 没发现一个nodejs/php的(还在维护并且功能完善的). 另外, 一些功能比较弱, 不支持权限/hook/pull-request就不在这里列出了.

    gitlab功能的确比较完善, 但是性能太差, 重启服务要等很久. 个人感觉Gogs/gitbucket应该可以尝试下.

  • chrome 插件 User-Agent Switcher +

    / 分类: 工具 / 9 Comments

    之前用的插件User-Agent Switcher for Chrome在开发版的chrome不能用了, 所以索性自己开发了一个.
    当然, 功能要比它更强大, 除了自动匹配域名使用不同的user-agent外, 还可以:

    • 根据关键词搜索User-Agent;
    • User-Agent列表可以tab切换焦点enter直接切换;
    • 快速添加/编辑/删除User-Agent和domain规则;
    • 备份/导入设置;

    User-Agent Switcher

    Ps: chrome插件开发者帐号要付款$5认证, 没法付款, 所以暂时还不能发布到chrome extensions.

    安装: https://raw.githubusercontent.com/kairyou/user-agent-switcher/master/build.crx
    下载到本地, 打开chrome://extensions/ 拖放到列表安装.

    源码: https://github.com/kairyou/user-agent-switcher

  • sublime利用ClosureCompiler和YUICompressor本地压缩

    / 分类: 工具,实践 / 1 Comment

    server端基本靠nodejs来压缩了, 本地也可能因为特殊需求而需要直接压缩js/css, 不同的系统node的兼容不算好, 不好配置统一的环境, 而且有些人也用不到到node. 所以想到了利用基于java的ClosureCompiler和YUICompressor(下面简称CC和YUI).

    写了2个ST的build tool, 源码:
    https://github.com/kairyou/SublimeGoogleClosureCompiler
    https://github.com/kairyou/SublimeYUICompressor
    在ST2/ST3(Windows/Mac)下面测试通过, Linux应该也能跑.
    如果有语法错误可以直接双击console面板的错误行, 就会跳到源文件的对应行.
    直接git clone或下载到ST插件目录就可以了.
    使用时在ST的tool-build system选择CC或YUI后, ctrl+b直接压缩(推荐js使用CC压缩, css使用YUI压缩).

    因为之前用editplus和vim时, 用到了淘宝压缩的cmd, 所以写cmd时copy了大部分代码, 节约了很多时间, 感谢.
    开发中也遇到几个蛋疼的问题, 花了不少功夫才解决了这些问题:
    sublime的build system设计的不够好, 如果console面板错误行没输出文件的绝对路径, 双击错误行不会跳转.
    YUI的输出错误不带路径, 所以需要自己再包一层cmd/bash脚本, 捕获输出并加上文件路径再返回给ST.
    而且YUI返回错误时还附带了一堆java信息, 需要过滤掉.
    另外, Windows下面cmd捕获/修改输出太弱了, 不得不写个hack来存放输出再读取再修改. 有兴趣的可以对比下SublimeYUICompressor/bin下面的cmd和sh文件就明白了.

    另外Windows下面要有%JAVA_HOME%的环境变量, 如果没有需要装JDK, 请查看https://github.com/kairyou/JDK, 里面有快速搭建说明.

  • Mac下配置mnmp环境

    / 分类: 工具,实践 / 9 Comments

    虽然比较喜欢玩下新语言, 但是php还是常会用到的. lnmp很多人都听过, 但是不能用在Mac上面, 另外还有个mnpp但在osx 10.8.3下面跑不起来.
    所以自己手动一步步安装, 整理了方便安装的bash脚本, 暂且叫mnmp吧, 实际上也是Mac+nginx+mysql+php, 也许有点标题党, 见谅见谅~ 不过总体上能为准备装mnmp的同学省掉不少弯路, 因为我参考一些文章安装时也碰到几个问题卡住了.

    安装:

    把: https://github.com/kairyou/mac-bash-scripts的脚本下载下来.
    安装前请确认安装了homebrew, 就不提了. 开始安装:
    bash切换到setup-mnmp.sh目录, 然后执行:sh setup-mnmp.sh 就等着自动安装吧.

    必要的一些配置:


    nginx:
    vim /usr/local/etc/nginx/nginx.conf
    http {...} 里面最后面加上: include vhost/*.conf; (大概是倒数第三行的位置)
    vim /usr/local/etc/nginx/vhost/default.conf , 添加类似下面的内容:

    server {
        listen       8080;
        server_name  dev.local;
        root   /Users/leon/Workspace;
        index  index.html index.htm index.php;
    
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
        #error_page  404 /404.html;
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {root html;}
        location ~ .*\.(php|php5)?$ {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            include fastcgi.conf;
        }
        location / {
            if (!-e $request_filename){
                rewrite ^/sitemap.xml$ /sitemap.php; # rewrite
            }
        }
        access_log off;
    }
    

    sudo sh -c "echo '127.0.0.1 dev.local' >> /etc/hosts"
    上面的nginx配置和命令是绑定http://dev.local作为域名, 绑定到/Users/leon/Workspace目录(域名和目录根据自己的需要修改吧).

    php-fpm:
    vim /usr/local/etc/php/5.6/php-fpm.conf, 找到并修改下面3行, 后面两个是要注释掉的:
    error_log = /tmp/php-fpm.log
    ;user = _www
    ;group = _www
    另外php.ini的路径: /usr/local/etc/php/5.6/php.ini, 如果有额外需求自己修改, 比如:
    date.timezone = Asia/Shanghai
    error_reporting = E_ALL

    mysql:
    基本不需要配置了, 配置文件在/usr/local/opt/mysql/my-new.cnf 如果没有就是 my.cnf.
    默认不需密码, 如果需要可以执行: mysql_secure_installation 一步步来, 本地开发意义不大.

    启动重启service脚本:

    设置权限: chmod +x ./mnmp.sh
    然后运行: ./mnmp.sh start | stop | restart 即可.
    推荐加到profile里面, 比如: echo "alias mnmp='/Users/你的路径/mnmp.sh'" >> ~/.bash_profile
    source ~/.bash_profile
    因为我不需要开机启动, 如果有需要开机启动的可以参考gist.github.com/mystix/3041577最下面的那几行.
    然后就可以直接: mnmp start 这样用了.

    Ps: 如果遇到类似这样的错误: "xxx" failed (13: Permission denied), 需要设定下权限:
    chmod 755 $HOME && chmod 755 $HOME/Documents/

    phpmyadmin:(可选)
    下载: www.phpmyadmin.net/home_page/downloads.php
    解压到nginx的conf指定的目录, config.sample.inc.php重命名为config.inc.php, 修改$cfg['Servers'][$i]['AllowNoPassword'] = true;
    Ps: 如果phpmyadmin报错:The mcrypt extension is missing. 可以关掉mnmp, 执行下:brew install php54-mcrypt
    之后打开: http://dev.local:8080/phpmyadmin 应该就OK了.