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

实践

  • discourse 插件开发

    / 分类: 开发,实践 / No Comments

    开发discourse插件, 依赖的知识: ES6/SCSS/Ember.js/Rails/handlebars.
    Ember是前端MVVM框架, 支持数据双向绑定/虚拟DOM, 模板引擎使用handlebars, 依赖jQuery(处理DOM兼容性操作), 遵循约定优于配置原则(类似Rails).

    discourse 本地环境搭建

    依赖: ruby, postgres, redis 需要提前安装好.

    • macOS 安装Ruby2.6

      brew install rbenv; rbenv init; rbenv install 2.6.2; # discourse依赖 Ruby 2.5+
    • (推荐) 用docker搭建本地 postgres, redis

      # code db.yml
      version: '3.1'
      services:
        redis:
          container_name: redis
          image: redis:alpine
          ports:
            - "6379:6379"
        postgres:
          container_name: postgres
          image: postgres:9-alpine
          ports:
            - "5432:5432"
          environment:
            - POSTGRES_USER=postgres
            - POSTGRES_PASSWORD=postgres
      # docker-compose up -d -f db.yml # 启动 postgresql/redis
      # docker restart postgres redis # 重启 postgresql/redis
    git clone https://github.com/discourse/discourse.git;
    # git checkout tags/v2.2.4; # 指定某个稳定的版本
    code config/database.yml # 设定 postgres 数据库信息
    development: # 设定正确用户名/密码
      username: name
      password: pass
      host: localhost
    bundle install; # 安装依赖
    bundle exec rake db:create db:migrate; # 创建数据库
    # rails r "SiteSetting.min_password_length=8;SiteSetting.min_admin_password_length=8;" # 设定密码最少8位
    rake admin:create # 创建用户, 输入Email/password/是否管理员
    # rails r "u=User.find_by_email('test@test.com'); u.password='11112222'; u.save!;" # 修改用户密码
    rails s -p 8000 # 启动论坛, 访问 localhost:8000

    创建plugin

    例子: 创建名为 DiscourseTest 的插件

    rails g plugin DiscourseTest # 创建插件, 自动创建以下文件:
    # plugins/discourse-test/README.md
    # plugins/discourse-test/LICENSE # 默认MIT
    # plugins/discourse-test/plugin.rb # 插件后端入口
    # plugins/discourse-test/assets/stylesheets/common/discourse-test.scss
    # plugins/discourse-test/assets/javascripts/initializers/discourse-test.es6 # 插件前端入口
    # plugins/discourse-test/config/settings.yml # 插件配置项
    # plugins/discourse-test/config/locales/client.en.yml # 扩展i18n语言包
    # plugins/discourse-test/config/locales/server.en.yml
    
    # 插件生成器有bug, 生成的js文件名 要手动修改:
    # discourse-test.es6 => discourse-test.js.es6
    
    # 方便 vscode 开发:
    code .gitignore # 增加3行:
    /jsapp/
    /adminjs/
    !/plugins/discourse-test # 插件路径
    
    code .gitmodules # 增加(方便vscode 管理多个插件):
    [submodule "plugins/discourse-test"]
        path = plugins/discourse-test
      url = git@github.com/username/discourse-test.git

    重启discourse后, 管理员登录论坛, 可以在 /admin/plugins 看到已安装的插件: DiscourseTest.
    开发模式: 修改scss页面会自动更新, 修改js文件需刷新页面.

    查看全文 »

  • Mac本地开发环境, apache/nginx绑定域名启用HTTPS

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

    创建本地ssl证书(使用lvh.me域名)

    mkdir ~/.ssl; cd ~/.ssl;
    openssl req -new -keyout lvh.me.key -x509 -nodes -new -out lvh.me.crt -subj "/CN=*.lvh.me" -reqexts SAN -extensions SAN -config <(cat /System/Library/OpenSSL/openssl.cnf <(printf '[SAN]\nsubjectAltName=DNS:lvh.me,DNS:*.lvh.me,DNS:*.dev.lvh.me')) -sha256 -days 3650;
    open lvh.me.crt; # Mac钥匙串 打开
    # 搜索 *.lvh, 双击添加的证书, 设置始终信任 (Trust - When using this certificate: Always Trust).

    lvh.me 是一个指向127.0.0.1的泛域名服务, 优点: 不需要改DNS/hosts, 各项目使用不同的域名方便隔离(比如cookies/密码管理器). 类似的还有xip.io, nip.io, localtest.me, fuf.me, vcap.me等.

    使用Apache或Nginx配置域名和虚拟机

    本地域名绑定 apache

    # 1. 编辑 `/etc/apache2/httpd.conf`, 添加行:
    ServerName localhost
    # 取消这些行的注释:
    Include /private/etc/apache2/extra/httpd-vhosts.conf
    LoadModule proxy_module libexec/apache2/mod_proxy.so
    LoadModule proxy_http_module libexec/apache2/mod_proxy_http.so
    LoadModule macro_module libexec/apache2/mod_macro.so
    LoadModule ssl_module libexec/apache2/mod_ssl.so
    Include /private/etc/apache2/extra/httpd-ssl.conf
    LoadModule socache_shmcb_module libexec/apache2/mod_socache_shmcb.so
    LoadModule http2_module libexec/apache2/mod_http2.so
    
    # 2. 编辑 `/private/etc/apache2/extra/httpd-vhosts.conf`, 增加:
    <Macro SSLLvh>
        SSLEngine on
        SSLCertificateFile /Users/leon/.ssl/lvh.me.crt
        SSLCertificateKeyFile /Users/leon/.ssl/lvh.me.key
        Protocols h2 http/1.1
    </Macro>
    <Macro Site>
        ServerName leon.lvh.me
        ProxyRequests off
        <Location />
            ProxyPass http://localhost:3000/
            ProxyPassReverse http://localhost:3000/
        </Location>
    </Macro>
    <VirtualHost *:80>
        Use Site
    </VirtualHost>
    <VirtualHost *:443>
       Use SSLLvh
       Use Site
    </VirtualHost>
    # 3. 启动Apache
    # sudo apachectl configtest # test
    sudo apachectl -k restart # 启动
    # sudo apachectl -e debug # print errors

    本地域名绑定 nginx

    sudo apachectl -k stop # 停止 apache 服务
    brew install nginx # 用brew安装
    # 编辑 `/usr/local/etc/nginx/nginx.conf`
    # listen 80; 改为: listen 80;
    # root   html; 改为:
    # root /Users/leon/Downloads;
    # autoindex on;
    # include servers/*; 改为: include conf.d/*.conf;
    
    chmod 755 /Users/leon/Downloads
    mkdir /usr/local/etc/nginx/conf.d;
    # 编辑 `/usr/local/etc/nginx/conf.d/test.conf`;
    server {
        listen 80;
        server_name leon.lvh.me;
        # SSL # include lvh_ssl.conf;
        listen 443 ssl http2;
        ssl_certificate /Users/leon/.ssl/lvh.me.crt;
        ssl_certificate_key /Users/leon/.ssl/lvh.me.key;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
        ssl_prefer_server_ciphers on;
        location / {
          # root /Users/leon/Downloads;
          # autoindex on;
          proxy_pass http://localhost:3000;
          proxy_set_header Host $host;
        }
    }
    # fix Permission denied while uploading
    sudo chmod o+x /usr/local/var
    sudo chown -vhR nobody:admin /usr/local/var/run/nginx
    # brew services list
    sudo brew services restart nginx # 启动
    # sudo brew services stop nginx
    sudo nginx -s reload # 重启

    接下来就可以使用 https://leon.lvh.me 访问本地项目了.

  • 使用letsencrypt自动生成和续期HTTPS证书

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

    相信一些同学注意到了, 本站启用了https, 域名改成了xhl.me, 服务也早就全都改用docker了.
    顺带介绍下之前搞的两个个docker项目: alpine-tengine, docker-backup.

    *本文主要介绍letsencrypt证书的创建和通配符HTTPS证书生成, 还有基于letsencrypt docker镜像实现证书自动续期.

    Let's Encrypt 是一个自动签发免费HTTPS证书的非营利机构, 生成的证书有3个月有效期, 到期可以免费续期.
    Certbot 是 Let's Encrypt 官方推荐的生成证书的客户端工具, 文档.

    使用letsencrypt-dns生成证书(支持通配符域名证书), 并自动续期

    letsencrypt-dns 集成了: certbot(证书生成命令行工具), Lexicon(DNS记录修改工具, 主流DNS服务商都支持).
    另外还自带了crontab 定时任务, 只要服务启动, 就会自动续期域名了.

    1. 创建, /etc/letsencrypt/domains.conf, 内容类似这样:
    *.domnain1.com domnain1.com
    *.domnain2.com domnain2.com
    2. 根据DNS PROVIDER信息验证, 并自动创建和续期证书

    下面的例子是拿dnspod举例. LEXICON支持主流的DNS服务, 所有支持的列表.

    docker run -it --rm --name letsencrypt2 \
        -v /etc/letsencrypt:/etc/letsencrypt \
        -v /var/run/docker.sock:/var/run/docker.sock \
        -e 'LETSENCRYPT_USER_MAIL=yourmail@gmail.com' \
        -e 'LEXICON_PROVIDER=dnspod' -e 'LEXICON_DNSPOD_USERNAME={dnspod_api_id}' -e 'LEXICON_DNSPOD_TOKEN={dnspod_api_token}' \
        adferrand/letsencrypt-dns

    如果是域名在godaddy或cloudflare, 可以这样:

    • godaddy API:
      -e 'LEXICON_PROVIDER=godaddy' -e 'LEXICON_GODADDY_KEY={{godaddy_key}}' -e 'LEXICON_GODADDY_SECRET={{godaddy_secret}}'
    • Cloudflare API:
      -e 'LEXICON_PROVIDER=cloudflare' -e 'LEXICON_CLOUDFLARE_USERNAME={{cloudflare_email}}' -e 'LEXICON_CLOUDFLARE_TOKEN={{cloudflare_api_key}}'
    3. 进阶: 续期后执行其他命令(比如重启Nginx)

    /etc/letsencrypt/domains.conf, 每行末尾可以加autocmd命令, 在续期后执行某个容器的shell命令, 比如:
    *.domnain1.com domnain1.com autocmd-containers=nginx:nginx -s reload
    续期后, 在容器名为nginx的容器中会执行: nginx -s reload
    另外, domains.conf最好保持最后一行有个换行(空行), 有时发现最后一行的域名没读到.

    查看全文 »

  • 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了.