构建工具升级
因为要拆分代码,便于管理,需要使用import
和export
,因此必须要引入webpack这样的打包工具到gulp中,使用webpack-stream,具体使用方法和其他的gulp插件类似,在pipe在这样插入就行了.pipe(webpack())
,配置方式和webpack一样。(webpack中引入babel-loader的过程就不赘述了)引入webpack后,开发流程和一起类似,gulp
启动测试服务器,使用webpack通过entry.js
打包代码,CSS和JSON相关流程不变。release时,增加了minify的流程,让js流程后的代码再压缩一遍。
另外,引入babel后,可以用ES6语法改写gulpfile.js
。最后的gulpfile.babel.js
像下面这样:
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
| import gulp from 'gulp'; import rename from 'gulp-rename'; import uglify from 'gulp-uglify'; import cleanCSS from 'gulp-clean-css'; import jsonminify from 'gulp-jsonminify'; import webserver from 'gulp-webserver'; import webpack from 'webpack-stream';
gulp.task('js', function () { return gulp.src('src/index.js') .pipe(webpack({ module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" } ] } })) .pipe(rename("index.js")) .pipe(gulp.dest('dist')); });
gulp.task('minify', function () { return gulp.src('dist/index.js') .pipe(uglify()) .pipe(rename("index.min.js")) .pipe(gulp.dest("dist")); })
gulp.task('css', function () { return gulp.src(['src/index.css']) .pipe(cleanCSS({compatibility: 'ie8'})) .pipe(gulp.dest('dist')); });
gulp.task('json', function () { return gulp.src('src/meta*.json') .pipe(jsonminify()) .pipe(gulp.dest('dist')) });
gulp.task('webserver', function() { gulp.src('./') .pipe(webserver({ livereload: true, directoryListing: true, open: true })); });
gulp.task('watch', function() { gulp.watch(['src/*.js', 'src/**/*.js', 'src/**/*.vue'], ['js']); gulp.watch('src/*.css', ['css']); gulp.watch('src/*.json', ['json']); })
gulp.task('assets', ['json', 'css', 'js']); gulp.task('default', ['assets', 'webserver', 'watch']); gulp.task("release", ['assets', 'minify']);
|
使用单文件组件
引入webpack后,开始高高兴兴地分模块拆分代码,却发现分组件使用Vue时,不是单纯地定义组件配置信息,然后传给入口组件就行。必须要引入全家桶,vue-loader
等工具,文件不得不用.vue这样的形式组织(现在开始觉得React组件的组织比Vue舒服了)。本来使用单文件的形式就是想尽量精简,可随着功能逐渐健全,看来重构也是避免不了的啊。在vue-loader的介绍里,居然还要通过vue-cli
来大一统,但是我一是想维持项目尽量轻量精简,使用gulp的工具链;二是项目已经写了很久了,全部迁移过去成本有些大。于是,通过vue-cli
新建样本项目,对着package.json
和webpack.config.js
一抄了事。
加上种种.vue
文件的相关配置,gulp.babel.js
最后长下面这样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| gulp.task('js', function () { return gulp.src('src/index.js') .pipe(webpack({ module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }, { test: /\.vue$/, loader: 'vue-loader'}, { test: /\.(png|jpg|gif|svg)$/, loader: 'file-loader', options: { name: '[name].[ext]?[hash]' } } ] }, resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' }, extensions: ['*', '.js', '.vue', '.json'] } })) .pipe(rename("index.js")) .pipe(gulp.dest('dist')); });
|
下面需要开始拆分代码了。根据React/Vue这样框架通常的设计经验,需要下面一些组成:
actions
存储状态管理的动作
components
存储相互解耦的”dumb”组件,最好和业务无关
constants
存储全局常量
containers
存储组织components
的业务容器组件
entry
存储入口文件
helper
存储工具函数
reducers
存储状态管理的reducers
settings
存储全局配置,通常用来初始化store
store
存储全局状态
templates
存储引入js的html文件
我的项目比较简单,一没有状态管理(后面复杂了之后可能会引入😂),二只有三个组件,只要上面的components
, constants
, containers
, helper
的就够用了。最后src下的文件目录大概像下面这样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ├── App.vue ├── components │ └── column │ └── Column.vue ├── constants │ └── index.js ├── containers │ ├── info │ │ └── Info.vue │ └── wall │ └── Wall.vue ├── helper │ └── utils.js ├── index.css └── index.js
|
在拆分时遇到了一些数据需要从最外层透传到子组件的情况,如res
, tag_list
, tag_keys
。不过他们是只读的,而且数目很少,所以并不需要状态管理,只用通过props传下去就行了。
新功能
重构完之后,终于可以写新功能了。新功能主要是增加两个伪路由,方便页面的分享(这个需求我之前遇到过几次了)。页面是spa类型的,所以前端路由可以采用hash或history H5 API来实现。同时也有许多在这个基础上了前端路由库,提供一站式解决方案。我的需求目前其实不需要完整的路由方案:
因此,设计上使用hash的方案,对于图片详情页,用!
开头,后接图片序号。对于搜索结果页,则没有开头的!
,仅使用/
隔开每一个搜索关键字。对hash的读写上,没有什么困难的地方:
- 读:
App.vue
根据hash注入对应的数据,更改默认视图,对于图片详情页,更改展示组件
- 写:切换组件时,记录当前数据到
location.hash
,方便直接复制链接分享
后面的计划
现在网站还是有点单调了。只能自娱自乐,没有互动。后面应该会考虑在每张图片接入Disqus的问题。