那么以后可能就是这样子。。。。
Repository: phodal/growth-ebook
Branch: gh-pages
Commit: 37b443cbd250
Files: 80
Total size: 530.7 KB
Directory structure:
gitextract_hamyp2r0/
├── .gitignore
├── CNAME
├── LICENSE
├── Makefile
├── README.md
├── assets/
│ └── article/
│ └── compressimages.py
├── build/
│ ├── author.html
│ ├── head.html
│ ├── metadata.xml
│ ├── share.html
│ ├── stats.html
│ └── title.txt
├── chapters/
│ ├── 0.0.0-prelude.md
│ ├── 1.0.md
│ ├── 1.1.0-setup.md
│ ├── 1.1.0-tool.md
│ ├── 1.1.1-env-osx.md
│ ├── 1.1.2-env-windows.md
│ ├── 1.1.3-env-linux.md
│ ├── 1.2-learn-language.md
│ ├── 1.3-web-basic.md
│ ├── 1.4.0-html.md
│ ├── 1.4.1-css.md
│ ├── 1.4.2-js.md
│ ├── 2.0.0-back-front.md
│ ├── 2.1.0-backend-language.md
│ ├── 2.1.2-mvc.md
│ ├── 2.1.3-serviceful.md
│ ├── 2.1.4-persistence.md
│ ├── 2.2.0-choice-frontend.md
│ ├── 2.2.2-communication.md
│ ├── 3.0.0-coding.md
│ ├── 3.0.1-builder.md
│ ├── 3.0.2-git.md
│ ├── 3.0.3-tasking.md
│ ├── 3.0.4-typing.md
│ ├── 3.0.5-knowledge.md
│ ├── 3.1.0-how-to-test.md
│ ├── 3.1.1-test-double.md
│ ├── 3.1.2-tdd.md
│ ├── 3.2.1-readable.md
│ ├── 3.2.2-refactor.md
│ ├── 3.2.3-intellij-refactor.md
│ ├── 3.3.0-refactor-to-pattern.md
│ ├── 4.0.0-golive.md
│ ├── 4.1.0-runenv.md
│ ├── 4.2.0-lnmp.md
│ ├── 4.2.1-cache.md
│ ├── 4.3.1-configurable.md
│ ├── 4.4.0-auto-deploy.md
│ ├── 5.0.0-data-analytics.md
│ ├── 5.1.0-lean.md
│ ├── 5.1.1-da.md
│ ├── 5.1.2-ga.md
│ ├── 5.2.0-performance.md
│ ├── 5.3.0-seo.md
│ ├── 5.4.0-first-ux.md
│ ├── 5.4.1-learn-design.md
│ ├── 6.0.0-cd.md
│ ├── 6.1.1-ci.md
│ ├── 6.2.1-cd.md
│ ├── 6.3.0-cl.md
│ ├── 7.0.0-legacy-system.md
│ ├── 7.1.1-legacy-code.md
│ ├── 7.1.2-change-code.md
│ ├── 7.2.1-refactor2.md
│ ├── 8.0.0-retro-rearch.md
│ ├── 8.1.1-summary.md
│ ├── 8.1.2-retro.md
│ ├── 8.2.0-arch-pattern.md
│ ├── 8.2.1-emergent-design.md
│ ├── 8.3.0-architecture.md
│ └── 8.3.1-seperate.md
├── css/
│ └── vendor.css
├── epub.css
├── growth.md
├── index.html
├── listings-setup.tex
├── style.css
└── template/
└── template.tex
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
growth.rtf
growth.mobi
growth.pdf
growth.epub
================================================
FILE: CNAME
================================================
growth.phodal.com
================================================
FILE: LICENSE
================================================
License
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
1. Definitions
"Collective Work" means a work, such as a periodical issue, anthology or encyclopedia, in which the Work in its entirety in unmodified form, along with one or more other contributions, constituting separate and independent works in themselves, are assembled into a collective whole. A work that constitutes a Collective Work will not be considered a Derivative Work (as defined below) for the purposes of this License.
"Derivative Work" means a work based upon the Work or upon the Work and other pre-existing works, such as a translation, musical arrangement, dramatization, fictionalization, motion picture version, sound recording, art reproduction, abridgment, condensation, or any other form in which the Work may be recast, transformed, or adapted, except that a work that constitutes a Collective Work will not be considered a Derivative Work for the purpose of this License. For the avoidance of doubt, where the Work is a musical composition or sound recording, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered a Derivative Work for the purpose of this License.
"Licensor" means the individual, individuals, entity or entities that offers the Work under the terms of this License.
"Original Author" means the individual, individuals, entity or entities who created the Work.
"Work" means the copyrightable work of authorship offered under the terms of this License.
"You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
2. Fair Use Rights. Nothing in this license is intended to reduce, limit, or restrict any rights arising from fair use, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws.
3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
to reproduce the Work, to incorporate the Work into one or more Collective Works, and to reproduce the Work as incorporated in the Collective Works; and,
to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission the Work including as incorporated in Collective Works.
The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats, but otherwise you have no rights to make Derivative Works. All rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights set forth in Sections 4(d) and 4(e).
4. Restrictions.The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
You may distribute, publicly display, publicly perform, or publicly digitally perform the Work only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy or phonorecord of the Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of a recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. When You distribute, publicly display, publicly perform, or publicly digitally perform the Work, You may not impose any technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Work itself to be made subject to the terms of this License. If You create a Collective Work, upon notice from any Licensor You must, to the extent practicable, remove from the Collective Work any credit as required by Section 4(c), as requested.
You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in connection with the exchange of copyrighted works.
If You distribute, publicly display, publicly perform, or publicly digitally perform the Work (as defined in Section 1 above) or Collective Works (as defined in Section 1 above), You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or (ii) if the Original Author and/or Licensor designate another party or parties (e.g. a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; the title of the Work if supplied; to the extent reasonably practicable, the Uniform Resource Identifier, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work. The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Collective Work, at a minimum such credit will appear, if a credit for all contributing authors of the Collective Work appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this clause for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.
For the avoidance of doubt, where the Work is a musical composition:
Performance Royalties Under Blanket Licenses. Licensor reserves the exclusive right to collect whether individually or, in the event that Licensor is a member of a performance rights society (e.g. ASCAP, BMI, SESAC), via that society, royalties for the public performance or public digital performance (e.g. webcast) of the Work if that performance is primarily intended for or directed toward commercial advantage or private monetary compensation.
Mechanical Rights and Statutory Royalties. Licensor reserves the exclusive right to collect, whether individually or via a music rights agency or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You create from the Work ("cover version") and distribute, subject to the compulsory license created by 17 USC Section 115 of the US Copyright Act (or the equivalent in other jurisdictions), if Your distribution of such cover version is primarily intended for or directed toward commercial advantage or private monetary compensation.
Webcasting Rights and Statutory Royalties. For the avoidance of doubt, where the Work is a sound recording, Licensor reserves the exclusive right to collect, whether individually or via a performance-rights society (e.g. SoundExchange), royalties for the public digital performance (e.g. webcast) of the Work, subject to the compulsory license created by 17 USC Section 114 of the US Copyright Act (or the equivalent in other jurisdictions), if Your public digital performance is primarily intended for or directed toward commercial advantage or private monetary compensation.
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND ONLY TO THE EXTENT OF ANY RIGHTS HELD IN THE LICENSED WORK BY THE LICENSOR. THE LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MARKETABILITY, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Collective Works (as defined in Section 1 above) from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
8. Miscellaneous
Each time You distribute or publicly digitally perform the Work (as defined in Section 1 above) or a Collective Work (as defined in Section 1 above), the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
Creative Commons Notice
Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor.
Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, Creative Commons does not authorize the use by either party of the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time. For the avoidance of doubt, this trademark restriction does not form part of this License.
Creative Commons may be contacted at https://creativecommons.org/.
================================================
FILE: Makefile
================================================
include_dir=build
source=chapters/*.md
title='Growth'
filename='growth'
all: html epub rtf pdf mobi
markdown:
awk 'FNR==1{print ""}{print}' $(source) > $(filename).md
html: markdown
pandoc -s $(filename).md -t html5 -o index.html -c style.css \
--include-in-header $(include_dir)/head.html \
--include-before-body $(include_dir)/author.html \
--include-before-body $(include_dir)/share.html \
--include-after-body $(include_dir)/stats.html \
--title-prefix "Growth: 全栈增长工程师指南" \
--normalize \
--smart \
--toc
epub: markdown
pandoc -s $(filename).md --normalize --smart -t epub -o $(filename).epub \
--epub-metadata $(include_dir)/metadata.xml \
--epub-stylesheet epub.css \
--epub-cover-image img/growth.jpg \
--title-prefix $(title) \
--normalize \
--smart \
--toc
rtf: markdown
pandoc -s $(filename).md -o $(filename).rtf \
--title-prefix $(title) \
--normalize \
--smart
pdf: markdown
# OS X: http://www.tug.org/mactex/
# Then find its path: find /usr/ -name "pdflatex"
# Then symlink it: ln -s /path/to/pdflatex /usr/local/bin
pandoc -s $(filename).md -o $(filename).pdf \
--title-prefix $(title) \
--listings -H listings-setup.tex \
--template=template/template.tex \
--normalize \
--smart \
--toc \
--latex-engine=`which xelatex`
mobi: epub
# Symlink bin: ln -s /path/to/kindlegen /usr/local/bin
kindlegen $(filename).epub
================================================
FILE: README.md
================================================
[Growth: 全栈增长工程师指南](https://github.com/phodal/growth-ebook)
===
Growth 纸质版《全栈应用开发:精益实践》,现已上市:

京东:[http://item.jd.com/12195442.html](http://item.jd.com/12195442.html)
当当:[http://product.dangdang.com/25077858.html](http://product.dangdang.com/25077858.html)
亚马逊:[https://www.amazon.cn/dp/B0722YJR89](https://www.amazon.cn/dp/B0722YJR89)
配合《[Growth: 全栈增长工程师实战](https://github.com/phodal/growth-in-action)》效果最佳。
> 依据在《[Repractise简介篇:Web开发的七天里](http://mp.weixin.qq.com/s?__biz=MjM5Mjg4NDMwMA==&mid=403171959&idx=1&sn=08f0717e2306efd7d80c8bb603e644d0#rd)》中所说的 Web 开发的七个步骤而展开的电子书。当然它也是一个 APP,它是一本关于如何成为全栈增长工程师的指南。
简介
--
**这是一本指导性的书籍——不要指望从这本书中学到所有的知识点,但是它可以帮你构建你的知识体系。**
我们都会学习,但是有时候我们只是不知道应该学习什么而已。
**这也是其他技术书籍所欠缺的。它可以告诉你,你可以学习什么,然后看什么书。**
对于有些人来说,成为全栈是因为:**来自社会的各个不同的中小公司,只靠一个领域的知识难以生存**
对于有些人来说,成为全栈是因为:**这个世界有太多的乐趣,在一颗树上吊死太可惜了**。
对于有些人来说,成为全栈是因为:**他们想去创业**。
而人们对于全栈有太多的误解——**认为全栈应该什么都会,什么都精通**。全栈只是因为我们对系统有整体性的认识,而不是精通整个系统。因为专家只精通某一个领域,总得有一个**架构师**来对系统把握。
我更愿意去改称这本书为《增长工程师指南》,去避免对这本书的误解。但是我想要去改变人们的观点,全栈更侧重于知识体系的增长。因为人们对于专家还有一个印象:古板。
我的其他电子书:
- 《[一步步搭建物联网系统](https://github.com/phodal/designiot)》
- 《[GitHub 漫游指南](https://github.com/phodal/github-roam)》
- 《[RePractise](https://github.com/phodal/repractise)》
在线预览:[http://growth.phodal.com/](http://growth.phodal.com/)
**下载**:
GitHub直接下载:[Epub版](https://github.com/phodal/growth-ebook/releases/download/0.9.9/growth.epub)、[Mobi版](https://github.com/phodal/growth-ebook/releases/download/0.9.9/growth.mobi)、[PDF版](https://github.com/phodal/growth-ebook/releases/download/0.9.9/growth.pdf)、[RTF版](https://github.com/phodal/growth-ebook/releases/download/0.9.9/growth.rtf)
百度盘:http://pan.baidu.com/s/1qYuy5Bm
没钱捧个人场: 关注我的微信公众号(扫描下面的二维码或搜索 Phodal).

有钱捧个钱场:

应用下载
---
目录
---
* [Growth: 全栈增长工程师指南](http://growth.phodal.com/#growth-全栈增长工程师指南)
* [全栈工程师是未来](http://growth.phodal.com/#全栈工程师是未来)
* [技术的革新史](http://growth.phodal.com/#技术的革新史)
* [软件开发的核心难题:沟通](http://growth.phodal.com/#软件开发的核心难题沟通)
* [大公司的专家与小公司的全栈](http://growth.phodal.com/#大公司的专家与小公司的全栈)
* [全栈工程师的未来:无栈](http://growth.phodal.com/#全栈工程师的未来无栈)
* [基础知识篇](http://growth.phodal.com/#基础知识篇)
* [工具只是辅助](http://growth.phodal.com/#工具只是辅助)
* [WebStorm 还是 Sublime?](http://growth.phodal.com/#webstorm-还是-sublime)
* [语言也是一种工具](http://growth.phodal.com/#语言也是一种工具)
* [提高效率的工具](http://growth.phodal.com/#提高效率的工具)
* [快速启动软件](http://growth.phodal.com/#快速启动软件)
* [IDE](http://growth.phodal.com/#ide)
* [DEBUG 工具](http://growth.phodal.com/#debug-工具)
* [终端或命令提示符](http://growth.phodal.com/#终端或命令提示符)
* [包管理](http://growth.phodal.com/#包管理)
* [环境搭建](http://growth.phodal.com/#环境搭建)
* [OS X](http://growth.phodal.com/#os-x)
* [Windows](http://growth.phodal.com/#windows)
* [GNU/Linux](http://growth.phodal.com/#gnulinux)
* [学好一门语言的艺术](http://growth.phodal.com/#学好一门语言的艺术)
* [一次语言学习体验](http://growth.phodal.com/#一次语言学习体验)
* [输出是最好的输入](http://growth.phodal.com/#输出是最好的输入)
* [如何应用一门新的技术](http://growth.phodal.com/#如何应用一门新的技术)
* [Web 编程基础](http://growth.phodal.com/#web-编程基础)
* [从浏览器到服务器](http://growth.phodal.com/#从浏览器到服务器)
* [从 HTML 到页面显示](http://growth.phodal.com/#从-html-到页面显示)
* [HTML](http://growth.phodal.com/#html)
* [hello,world](http://growth.phodal.com/#helloworld)
* [中文?](http://growth.phodal.com/#中文)
* [其他 HTML 标记](http://growth.phodal.com/#其他-html-标记)
* [小结](http://growth.phodal.com/#小结-1)
* [CSS](http://growth.phodal.com/#css)
* [简介](http://growth.phodal.com/#简介)
* [样式与目标](http://growth.phodal.com/#样式与目标)
* [选择器](http://growth.phodal.com/#选择器)
* [更有趣的 CSS](http://growth.phodal.com/#更有趣的-css)
* [JavaScript](http://growth.phodal.com/#javascript)
* [hello,world](http://growth.phodal.com/#helloworld-1)
* [JavaScriptFul](http://growth.phodal.com/#javascriptful)
* [面向对象](http://growth.phodal.com/#面向对象)
* [其他](http://growth.phodal.com/#其他)
* [前端与后台](http://growth.phodal.com/#前端与后台)
* [后台语言选择](http://growth.phodal.com/#后台语言选择)
* [JavaScript](http://growth.phodal.com/#javascript-1)
* [Python](http://growth.phodal.com/#python)
* [Java](http://growth.phodal.com/#java)
* [PHP](http://growth.phodal.com/#php)
* [其他](http://growth.phodal.com/#其他-1)
* [MVC](http://growth.phodal.com/#mvc)
* [Model](http://growth.phodal.com/#model)
* [View](http://growth.phodal.com/#view)
* [Controller](http://growth.phodal.com/#controller)
* [更多](http://growth.phodal.com/#更多-1)
* [后台即服务](http://growth.phodal.com/#后台即服务)
* [API 演进史](http://growth.phodal.com/#api-演进史)
* [后台即服务](http://growth.phodal.com/#后台即服务-1)
* [数据持久化](http://growth.phodal.com/#数据持久化)
* [文件存储](http://growth.phodal.com/#文件存储)
* [数据库](http://growth.phodal.com/#数据库)
* [搜索引擎](http://growth.phodal.com/#搜索引擎)
* [前端框架选择](http://growth.phodal.com/#前端框架选择)
* [Angular](http://growth.phodal.com/#angular)
* [React](http://growth.phodal.com/#react)
* [Vue](http://growth.phodal.com/#vue)
* [jQuery 系](http://growth.phodal.com/#jquery-系)
* [前台与后台交互](http://growth.phodal.com/#前台与后台交互)
* [Ajax](http://growth.phodal.com/#ajax)
* [JSON](http://growth.phodal.com/#json)
* [WebSocket](http://growth.phodal.com/#websocket)
* [编码](http://growth.phodal.com/#编码)
* [编码过程](http://growth.phodal.com/#编码过程)
* [Web 应用的构建系统](http://growth.phodal.com/#web-应用的构建系统)
* [Web 应用的构建过程](http://growth.phodal.com/#web-应用的构建过程)
* [Web 应用的构建实战](http://growth.phodal.com/#web-应用的构建实战)
* [Git 与版本控制](http://growth.phodal.com/#git-与版本控制)
* [版本控制](http://growth.phodal.com/#版本控制)
* [Git](http://growth.phodal.com/#git)
* [Tasking](http://growth.phodal.com/#tasking)
* [如何 Tasking 一本书](http://growth.phodal.com/#如何-tasking-一本书)
* [Tasking 开发任务](http://growth.phodal.com/#tasking-开发任务)
* [写代码只是在码字](http://growth.phodal.com/#写代码只是在码字)
* [内置索引与外置引擎](http://growth.phodal.com/#内置索引与外置引擎)
* [门户网站](http://growth.phodal.com/#门户网站)
* [内置索引与外置引擎](http://growth.phodal.com/#内置索引与外置引擎-1)
* [如何编写测试](http://growth.phodal.com/#如何编写测试)
* [测试金字塔](http://growth.phodal.com/#测试金字塔)
* [如何测试](http://growth.phodal.com/#如何测试)
* [测试替身](http://growth.phodal.com/#测试替身)
* [Stub](http://growth.phodal.com/#stub)
* [Mock](http://growth.phodal.com/#mock)
* [测试驱动开发](http://growth.phodal.com/#测试驱动开发)
* [红-绿-重构](http://growth.phodal.com/#红-绿-重构)
* [测试先行](http://growth.phodal.com/#测试先行)
* [可读的代码](http://growth.phodal.com/#可读的代码)
* [命名](http://growth.phodal.com/#命名)
* [函数长度](http://growth.phodal.com/#函数长度)
* [其他](http://growth.phodal.com/#其他-2)
* [代码重构](http://growth.phodal.com/#代码重构)
* [重命名](http://growth.phodal.com/#重命名)
* [提取变量](http://growth.phodal.com/#提取变量)
* [提炼函数](http://growth.phodal.com/#提炼函数)
* [Intellij Idea 重构](http://growth.phodal.com/#intellij-idea-重构)
* [提炼函数](http://growth.phodal.com/#提炼函数-1)
* [内联函数](http://growth.phodal.com/#内联函数)
* [查询取代临时变量](http://growth.phodal.com/#查询取代临时变量)
* [重构到设计模式](http://growth.phodal.com/#重构到设计模式)
* [过度设计与设计模式](http://growth.phodal.com/#过度设计与设计模式)
* [上线](http://growth.phodal.com/#上线)
* [隔离与运行环境](http://growth.phodal.com/#隔离与运行环境)
* [隔离硬件:虚拟机](http://growth.phodal.com/#隔离硬件虚拟机)
* [隔离操作系统:容器虚拟化](http://growth.phodal.com/#隔离操作系统容器虚拟化)
* [隔离底层:Servlet 容器](http://growth.phodal.com/#隔离底层servlet-容器)
* [隔离依赖版本:虚拟环境](http://growth.phodal.com/#隔离依赖版本虚拟环境)
* [隔离运行环境:语言虚拟机](http://growth.phodal.com/#隔离运行环境语言虚拟机)
* [隔离语言:DSL](http://growth.phodal.com/#隔离语言dsl)
* [LNMP 架构](http://growth.phodal.com/#lnmp-架构)
* [GNU/Linux](http://growth.phodal.com/#gnulinux-1)
* [HTTP 服务器](http://growth.phodal.com/#http-服务器)
* [Web 缓存](http://growth.phodal.com/#web-缓存)
* [数据库端缓存](http://growth.phodal.com/#数据库端缓存)
* [应用层缓存](http://growth.phodal.com/#应用层缓存)
* [前端缓存](http://growth.phodal.com/#前端缓存)
* [客户端缓存](http://growth.phodal.com/#客户端缓存)
* [HTML5 离线缓存](http://growth.phodal.com/#html5-离线缓存)
* [可配置](http://growth.phodal.com/#可配置)
* [环境配置](http://growth.phodal.com/#环境配置)
* [运行机制](http://growth.phodal.com/#运行机制)
* [功能开关](http://growth.phodal.com/#功能开关)
* [自动化部署](http://growth.phodal.com/#自动化部署)
* [依赖与包仓库](http://growth.phodal.com/#依赖与包仓库)
* [构建软件包](http://growth.phodal.com/#构建软件包)
* [上传和安装软件包](http://growth.phodal.com/#上传和安装软件包)
* [数据分析](http://growth.phodal.com/#数据分析)
* [构建-衡量-学习](http://growth.phodal.com/#构建-衡量-学习)
* [想法-构建](http://growth.phodal.com/#想法-构建)
* [产品-衡量](http://growth.phodal.com/#产品-衡量)
* [数据-学习](http://growth.phodal.com/#数据-学习)
* [数据分析](http://growth.phodal.com/#数据分析-1)
* [识别需求](http://growth.phodal.com/#识别需求)
* [收集数据](http://growth.phodal.com/#收集数据)
* [分析数据](http://growth.phodal.com/#分析数据)
* [展示数据](http://growth.phodal.com/#展示数据)
* [用户数据分析:Google Analytics](http://growth.phodal.com/#用户数据分析google-analytics)
* [受众群体](http://growth.phodal.com/#受众群体)
* [流量获取](http://growth.phodal.com/#流量获取)
* [移动应用](http://growth.phodal.com/#移动应用)
* [网站性能](http://growth.phodal.com/#网站性能)
* [网站性能监测](http://growth.phodal.com/#网站性能监测)
* [网站性能](http://growth.phodal.com/#网站性能-1)
* [SEO](http://growth.phodal.com/#seo)
* [爬虫与索引](http://growth.phodal.com/#爬虫与索引)
* [什么样的网站需要 SEO?](http://growth.phodal.com/#什么样的网站需要-seo)
* [SEO 基础知识](http://growth.phodal.com/#seo-基础知识)
* [内容](http://growth.phodal.com/#内容)
* [UX 入门](http://growth.phodal.com/#ux-入门)
* [什么是 UX](http://growth.phodal.com/#什么是-ux)
* [什么是简单?](http://growth.phodal.com/#什么是简单)
* [进阶](http://growth.phodal.com/#进阶)
* [用户体验要素](http://growth.phodal.com/#用户体验要素)
* [认知设计](http://growth.phodal.com/#认知设计)
* [流](http://growth.phodal.com/#流)
* [持续交付](http://growth.phodal.com/#持续交付)
* [持续集成](http://growth.phodal.com/#持续集成)
* [持续集成系统](http://growth.phodal.com/#持续集成系统)
* [持续集成流程](http://growth.phodal.com/#持续集成流程)
* [持续交付](http://growth.phodal.com/#持续交付-1)
* [基础设施](http://growth.phodal.com/#基础设施)
* [持续部署](http://growth.phodal.com/#持续部署)
* [持续学习](http://growth.phodal.com/#持续学习)
* [持续阅读](http://growth.phodal.com/#持续阅读)
* [持续编程](http://growth.phodal.com/#持续编程)
* [持续写作](http://growth.phodal.com/#持续写作)
* [遗留系统与修改代码](http://growth.phodal.com/#遗留系统与修改代码)
* [遗留代码](http://growth.phodal.com/#遗留代码)
* [遗留代码](http://growth.phodal.com/#遗留代码-1)
* [如何修改遗留代码](http://growth.phodal.com/#如何修改遗留代码)
* [修改遗留代码](http://growth.phodal.com/#修改遗留代码)
* [网站重构](http://growth.phodal.com/#网站重构)
* [速度优化](http://growth.phodal.com/#速度优化)
* [功能加强](http://growth.phodal.com/#功能加强)
* [模块重构](http://growth.phodal.com/#模块重构)
* [回顾与架构设计](http://growth.phodal.com/#回顾与架构设计)
* [自我总结](http://growth.phodal.com/#自我总结)
* [吾日三省吾身](http://growth.phodal.com/#吾日三省吾身)
* [Retro](http://growth.phodal.com/#retro)
* [Retro 的过程](http://growth.phodal.com/#retro-的过程)
* [三个维度](http://growth.phodal.com/#三个维度)
* [架构模式](http://growth.phodal.com/#架构模式)
* [预设计式架构](http://growth.phodal.com/#预设计式架构)
* [演进式架构:拥抱变化](http://growth.phodal.com/#演进式架构拥抱变化)
* [浮现式设计](http://growth.phodal.com/#浮现式设计)
* [意图导向](http://growth.phodal.com/#意图导向)
* [重构](http://growth.phodal.com/#重构)
* [模式与演进](http://growth.phodal.com/#模式与演进)
* [每个人都是架构师](http://growth.phodal.com/#每个人都是架构师)
* [如何构建一个博客系统](http://growth.phodal.com/#如何构建一个博客系统)
* [相关阅读资料](http://growth.phodal.com/#相关阅读资料)
* [架构解耦](http://growth.phodal.com/#架构解耦)
* [从 MVC 与微服务](http://growth.phodal.com/#从-mvc-与微服务)
* [CQRS](http://growth.phodal.com/#cqrs)
* [CQRS 结合微服务](http://growth.phodal.com/#cqrs-结合微服务)
Contributors
---
- [aidewoode](https://github.com/aidewoode)
- [Evan Lau](https://github.com/lolosssss)
- [loveisbug](https://github.com/loveisbug)
- [wangcongyi](https://github.com/wangcongyi)
- [wangyufeng0615](https://github.com/wangyufeng0615)
License
---
[](https://www.phodal.com/) [](https://www.phodal.com/)
© 2015~2016 [Phodal Huang](https://www.phodal.com). This code is distributed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 License. See `LICENSE` in this directory.
[待我代码编成,娶你为妻可好](http://www.xuntayizhan.com/blog/ji-ke-ai-qing-zhi-er-shi-dai-wo-dai-ma-bian-cheng-qu-ni-wei-qi-ke-hao-wan/)
================================================
FILE: assets/article/compressimages.py
================================================
from PIL import Image, ImageFile
from sys import exit, stderr
from os.path import getsize, isfile, isdir, join
from os import remove, rename, walk, stat
from stat import S_IWRITE
from shutil import move
from argparse import ArgumentParser
from abc import ABCMeta, abstractmethod
class ProcessBase:
"""Abstract base class for file processors."""
__metaclass__ = ABCMeta
def __init__(self):
self.extensions = []
self.backupextension = 'compressimages-backup'
@abstractmethod
def processfile(self, filename):
"""Abstract method which carries out the process on the specified file.
Returns True if successful, False otherwise."""
pass
def processdir(self, path):
"""Recursively processes files in the specified directory matching
the self.extensions list (case-insensitively)."""
filecount = 0 # Number of files successfully updated
for root, dirs, files in walk(path):
for file in files:
# Check file extensions against allowed list
lowercasefile = file.lower()
matches = False
for ext in self.extensions:
if lowercasefile.endswith('.' + ext):
matches = True
break
if matches:
# File has eligible extension, so process
fullpath = join(root, file)
if self.processfile(fullpath):
filecount = filecount + 1
return filecount
class CompressImage(ProcessBase):
"""Processor which attempts to reduce image file size."""
def __init__(self):
ProcessBase.__init__(self)
self.extensions = ['jpg', 'jpeg', 'png']
def processfile(self, filename):
"""Renames the specified image to a backup path,
and writes out the image again with optimal settings."""
try:
# Skip read-only files
if (not stat(filename)[0] & S_IWRITE):
print 'Ignoring read-only file "' + filename + '".'
return False
# Create a backup
backupname = filename + '.' + self.backupextension
if isfile(backupname):
print 'Ignoring file "' + filename + '" for which existing backup file is present.'
return False
rename(filename, backupname)
except Exception as e:
stderr.write('Skipping file "' + filename + '" for which backup cannot be made: ' + str(e) + '\n')
return False
ok = False
try:
# Open the image
with open(backupname, 'rb') as file:
img = Image.open(file)
# Check that it's a supported format
format = str(img.format)
if format != 'PNG' and format != 'JPEG':
print 'Ignoring file "' + filename + '" with unsupported format ' + format
return False
# This line avoids problems that can arise saving larger JPEG files with PIL
ImageFile.MAXBLOCK = img.size[0] * img.size[1]
# The 'quality' option is ignored for PNG files
img.save(filename, quality=90, optimize=True)
# Check that we've actually made it smaller
origsize = getsize(backupname)
newsize = getsize(filename)
if newsize >= origsize:
print 'Cannot further compress "' + filename + '".'
return False
# Successful compression
ok = True
except Exception as e:
stderr.write('Failure whilst processing "' + filename + '": ' + str(e) + '\n')
finally:
if not ok:
try:
move(backupname, filename)
except Exception as e:
stderr.write('ERROR: could not restore backup file for "' + filename + '": ' + str(e) + '\n')
return ok
class RestoreBackupImage(ProcessBase):
"""Processor which restores image from backup."""
def __init__(self):
ProcessBase.__init__(self)
self.extensions = [self.backupextension]
def processfile(self, filename):
"""Moves the backup file back to its original name."""
try:
move(filename, filename[: -(len(self.backupextension) + 1)])
return True
except Exception as e:
stderr.write('Failed to restore backup file "' + filename + '": ' + str(e) + '\n')
return False
class DeleteBackupImage(ProcessBase):
"""Processor which deletes backup image."""
def __init__(self):
ProcessBase.__init__(self)
self.extensions = [self.backupextension]
def processfile(self, filename):
"""Deletes the specified file."""
try:
remove(filename)
return True
except Exception as e:
stderr.write('Failed to delete backup file "' + filename + '": ' + str(e) + '\n')
return False
if __name__ == "__main__":
# Argument parsing
modecompress = 'compress'
moderestorebackup = 'restorebackup'
modedeletebackup = 'deletebackup'
parser = ArgumentParser(description='Reduce file size of PNG and JPEG images.')
parser.add_argument(
'path',
help='File or directory name')
parser.add_argument(
'--mode', dest='mode', default=modecompress,
choices=[modecompress, moderestorebackup, modedeletebackup],
help='Mode to run with (default: ' + modecompress + '). '
+ modecompress + ': Compress the image(s). '
+ moderestorebackup + ': Restore the backup images (valid for directory path only). '
+ modedeletebackup + ': Delete the backup images (valid for directory path only).')
args = parser.parse_args()
# Construct processor requested mode
if args.mode == modecompress:
processor = CompressImage()
elif args.mode == moderestorebackup:
processor = RestoreBackupImage()
elif args.mode == modedeletebackup:
processor = DeleteBackupImage()
# Run according to whether path is a file or a directory
if isfile(args.path):
if args.mode != modecompress:
stderr.write('Mode "' + args.mode + '" supported on directories only.\n')
exit(1)
processor.processfile(args.path)
elif isdir(args.path):
filecount = processor.processdir(args.path)
print '\nSuccessfully updated file count: ' + str(filecount)
else:
stderr.write('Invalid path "' + args.path + '"\n')
exit(1)
================================================
FILE: build/author.html
================================================
By Phodal (Follow Me: 微博、知乎、SegmentFault)
GitHub: Growth: 全栈增长工程师指南

京东:http://item.jd.com/12195442.html
当当: http://product.dangdang.com/25077858.html
亚马逊: https://www.amazon.cn/dp/B0722YJR89
阅读过程中遇到语法错误、拼写错误、技术错误等等,不妨来个Pull Request,这样可以帮助到其他阅读这本电子书的童鞋。
我的其他电子书:
微信公众号

================================================
FILE: build/head.html
================================================
================================================
FILE: build/metadata.xml
================================================
hello,world
3. 保存为->"helloworld.html",
4. 双击打开这个文件。 正常情况下都应该是用你的默认浏览器打开。只要是一个正常工作的现代浏览器,都应该可以看到上面显示的是"Hello,world"。
这才是最短的 hello,world 程序,但是呢?在 Ruby 中会是这样子的
``` bash
2.0.0-p353 :001 > p "hello,world"
"hello,world"
=> "hello,world"
2.0.0-p353 :002 >
```
等等,如果你了解过 HTML 的话,会觉得这一点都不符合语法规则,但是他工作了,没有什么比安装完 Nginx 后看到 It works! 更让人激动了。
遗憾的是,它可能无法在所有的浏览器上工作,所以我们需要去调试其中的 bug。
####调试 hello,world
我们会发现我们的代码在浏览器中变成了下面的代码,如果你和我一样用的是 Chrome,那么你可以右键浏览器中的空白区域,点击审查元素,就会看到下面的代码。
``` html
hello,world
```
这个才是真正能在大部分浏览器上工作的代码,所以复制它到编辑器里吧。
####说说 hello,world
我很不喜欢其中的<\*>*>,但是我也没有找到别的方法来代替它们,所以这是一个设计得当的语言。甚至大部分人都说这算不上是一门真正的语言,不过 HTML 的原义是
> 超文本标记语言
所以我们可以发现其中的关键词是标记——markup,也就是说 html 是一个 markup,head 是一个 markup,body 也是一个 markup。
然而,我们真正工作的代码是在 body 里面,至于为什么是在这里面,这个问题就太复杂了。打个比方来说:
1. 我们所使用的汉语是人类用智慧创造的,我们所正在学的这门语言同样也是人类创造的。
2. 我们在自己的语言里遵循着 **桌子是桌子,凳子是凳子** 的原则,很少有人会问为什么。
###中文?
所以我们也可以把计算机语言与现实世界里用于交流沟通的语言划上一个等号。而我们所要学习的语言,并不是我们最熟悉的汉语语言,所以我们便觉得这些很复杂,但是如果我们试着用汉语替换掉上面的代码的话
```HTML
<语言>
<头><结束头>
<身体>你好,世界<结束身体>
<结束语言>
```
这看上去很奇怪,只是因为是直译过去的原因,也许你会觉得这样会好理解一点,但是输入上可就一点儿也不方便,因为这键盘本身就不适合我们去输入汉字,同时也意味着可能你输入的会有问题。
让我们把上面的代码代替掉原来的代码然后保存,打开浏览器会看到下面的结果
```HTML
<语言> <头><结束头> <身体>你好,世界<结束身体> <结束语言>
```
更不幸的结果可能是
```HTML
<璇█> <澶�><缁撴潫澶�> <韬綋>浣犲ソ锛屼笘鐣�<缁撴潫韬綋> <缁撴潫璇█>
```
这是一个编码问题,对中文支持不友好。
我们把上面的代码改为和标记语言一样的结构
```HTML
<语言>
<头>头>
<身体>你好,世界身体>
语言>
```
于是我们看到的结果便是
```HTML
<语言> <头> <身体>你好,世界
```
被 Chrome 浏览器解析成什么样了?
``` html
<语言>
<头>
<身体>你好,世界
```
以``结尾的是注释,写给人看的代码,不是给机器看的,所以机器不会去理解这些代码。
但是当我们把代码改成
```HTML
Red
``` 只是, ``` javascript var para=document.getElementById("para"); para.style.color="blue"; ``` 将字体变成了蓝色,CSS+HTML 让页面有序的工作着,但是 JavaScript 却打乱了这些秩序,有着唯恐世界不乱的精彩,也难怪被冠以小三之名了——或许终于可以理解,为什么以前人们对于 JavaScript 没有好感了——不过这里要讲的是正室,也就是 CSS,这时还没有 JavaScript。  ###简介 这不是一篇专业讲述 CSS 的书籍,所以我不会去说 CSS 是怎么来的,有些东西我们既然可以很容易从其他地方知道,也就不需要花太多时间去重复。诸如重构等这些的目的之一也在于去除重复的代码,不过有些重复是不可少的,也是有必要的,而通常这些东西可能是由其他地方复制过来的。 到目前为止我们没有依赖于任何特殊的硬件或者是软件,对于我们来说我们最基本的需求就是一台电脑,或者可以是你的平板电脑,当然也可以是你的智能手机,因为他们都有个浏览器,而这些都是能用的,对于我们的 CSS 来说也不会有例外的。 CSS(Cascading Style Sheets),到今天我也没有记得他的全称,CSS 还有一个中文名字是层叠式样式表,事实上翻译成什么可能并不是我们关心的内容,我们需要关心的是他能做些什么。作为三剑客之一,它的主要目的在于可以让我们方便灵活地去控制 Web 页面的外观表现。我们可以用它做出像淘宝一样复杂的界面,也可以像我们的书本一样简单,不过如果要和我们书本一样简单的话,可能不需要用到 CSS。HTML 一开始就是依照报纸的格式而设计的,我们还可以继续用上面说到的编辑器,又或者是其他的。如果你喜欢 DreamWeaver 那也不错,不过一开始使用 IDE 可无助于我们写出良好的代码。 忘说了,CSS 也是有版本的,和 Windows,Linux 内核等等一样,但是更新可能没有那么频繁,HTML 也是有版本的,JavaScript 也是有版本的,复杂的东西不是当前考虑的内容。 ####代码结构 对于我们的上面的 Red 示例来说,如果没有一个好的结构,那么以后可能就是这样子。 ```HTML如果没有一个好的结构
那么以后可能就是这样子。。。。
``` 虽然我们看到的还是一样的:  于是我们就按各种书上的建议重新写了上面的代码 ```HTML如果没有一个好的结构
那么以后可能就是这样子。。。。
``` 总算比上面好看也好理解多了,这只是临时的用法,当文件太大的时候,正式一点的写法应该如下所示: ```HTML如果没有一个好的结构
那么以后可能就是这样子。。。。
``` 我们需要 ```HTML如果没有一个好的结构
那么以后可能就是这样子。。。。
``` 然后我们有一个像 app.js 一样的 style.css 放在同目录下,而他的内容便是 ```CSS .para{ font-size: 22px; color: #f00; text-align: center; padding-left: 20px; } .para2{ font-size: 44px; color: #3ed; text-indent: 2em; padding-left: 2em; } ``` 这代码和 JS 的代码有如此多的相似 ```javascript var para={ font_size: '22px', color: '#f00', text_align: 'center', padding_left: '20px', } ``` 而22px、20px以及#f00都是数值,因此: ```javascript var para={ font_size: 22px, color: #f00, text_align: center, padding_left: 20px, } ``` 目测差距已经尽可能的小了,至于这些话题会在以后讨论到,如果要让我们的编译器更正确的工作,那么我们就需要非常多这样的符号,除非你乐意去理解: ```lisp (dotimes (i 4) (print i)) ``` 总的来说我们减少了符号的使用,但是用 lisp 便带入了更多的括号,不过这是一种简洁的表达方式,也许我们可以在其他语言中看到。 ``` \d{2}/[A-Z][a-z][a-z]/\d{4} ``` 上面的代码,是为了从一堆数据中找出“某日/某月/某年”。如果一开始不理解那是正则表达式,就会觉得那个很复杂。 这门语言可能是为设计师而设计的,但是设计师大部分还是不懂编程的,不过相对来说这门语言还是比其他语言简单易懂一些。 ###样式与目标 如下所示,就是我们的样式 ```css .para{ font-size: 22px; color: #f00; text-align: center; padding-left: 20px; } ``` 我们的目标就是 > 如果没有一个好的结构 所以样式和目标在这里牵手了,问题是他们是如何在一起的呢?下面就是 CSS 与 HTML 沟通的重点所在了: ###选择器 我们用到的选择器叫做类选择器,也就是 class,或者说应该称之为 class 选择器更合适。与类选择器最常一起出现的是 ID 选择器,不过这个适用于比较高级的场合,诸如用 JS 控制 DOM 的时候就需要用到 ID 选择器。而基本的选择器就是如下面的例子: ```css p.para{ color: #f0f; } ``` 将代码添加到 style.css 的最下面会发现“如果没有一个好的结构”变成了粉红色,当然我们还会有这样的写法 ```css p>.para{ color: #f0f; } ``` 为了产生上面的特殊的样式,虽然不好看,但是我们终于理解什么叫层叠样式了,下面的代码的权重比上面高,也因此有更高的优先规则。 而通常我们可以通过一个 ```css p{ text-align: left; } ``` 这样的元素选择器来给予所有的 p 元素一个左对齐。 还有复杂一点的复合型选择器,下面的是 HTML 文件 ```html如果没有一个好的结构
那么以后可能就是这样子。。。。
那么以后可能就是这样子。。。。