前言
之前自己用Laravel写了个博客, 用了一段时间果断弃之, 又用回了原来的Hexo, 上网找了下主题, 没找到自己想要的, 于是决定自己写一款主题(在写主题的过程倒是找到了很多自己觉得不错的2333), 这篇文章只是用来记录一下最近这段时间写这个主题的过程, 中间存在着很多的问题, 主题目前还没有正式完成, 最近实习 + 毕设搞得比较颓, 9月份之后会逐步完善修复。
hexo-theme-cube
cube-generator
示例网站
其中cube-generator
是主题的生成器, 通过运行对应的gulp命令能够重新生成主题cube
构建主题
看了一些github上的主题项目, 很多都是ES5 + jQuery的实现方式, 于是自己有了一个想法,用ES6来写这个主题样式, 最终代码是要转化为ES5的, 那么就需要babel进行转换了, 又因为写样式决定采用SaSS, 所以就决定用gulp进行自动化构建, 所以最终的决定是:
- gulp中利用
browserify + babelify
对前端代码进行ES6到ES5的转换, Babel转换的规则写在babelify
上面, js代码的入口规定为source/js/app.js
,app.js
中import
对应功能的js代码, gulp进行bundle script
的生成代码如下:
const b = browserify({
cache: {},
packageCache: {},
entries: path.join('./source/js/app.js'),
debug: true
})
// 配置babel转换规则
b.transform(babelify, {
presets: ['env', 'es2015', 'stage-2'],
plugins: [['transform-runtime', {
'polyfill': true,
'regenerator': true
}]]
})
gulp.task('buildScript', bundle)
// b.on('update', bundle)
// bundle生成script.js并且放在cube/source/js/script.js上面
function bundle() {
return b.bundle()
.on('error', err => console.log(err))
.pipe(source('script.js'))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(uglify())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(path.join(Path.theme, Path.source, '/js')))
}
JS的部分如下所示:
- 在gulp中利用
gulp-inject
, 将source/sass/
目录下除了style.scss
的.scss
文件用@import
的方式进行注入,最后再对style.scss
用gulp-sass
进行编译生成最终的css文件, 代码如下:
// highlight和lightgallery已经在其他文件通过@import的方式引用了索引文件
// 所以这里不注入对应文件夹里面的文件
function buildStyle() {
const injectFiles = gulp.src([
path.join(Path.source, 'sass/*.scss'),
'!' + path.join(Path.source, 'sass/highlight/*.scss'),
'!' + path.join(Path.source, 'sass/lightgallery/*.scss'),
'!' + path.join(Path.source, '/sass/style.scss')
], { read: false })
const injectOptions = {
transform(filePath) {
filePath = filePath.replace(`${Path.source}/sass/`, '');
filePath = filePath.replace('_', '');
return `@import "${filePath}";`
},
starttag: '// injector',
endtag: '// endinjector',
addRootSlash: false
}
return gulp.src(path.join(Path.source, '/sass/style.scss'))
.pipe(Inject(injectFiles, injectOptions))
.pipe(Sass())
.pipe(postcss([ autoprefixer() ]))
.pipe(cleanCss({debug: true}))
.pipe(gulp.dest(path.join(Path.theme, Path.source, '/css')))
}
- 将上面两部生成的
script.js
和style.css
注入到header.ejs
和layout.ejs
(注入的其实是ejs的模板写法), 然后将ejs文件,字体和图片等静态资源移动到主题文件夹中,将主题文件夹放置到Hexo站点的themes文件夹里面, 完成主题的生成:
gulp.task('injectStyle', ['buildStyle'], () => {
const injectStyle = gulp.src(path.join(Path.theme, Path.source,'/css/style.css'), {
read: false
})
const injectOptions = {
starttag: '<!-- inject:style -->',
addRootSlash: false,
transform(filePath) {
return `<link href="<%- url_for('css/${filePath}') %>" rel="stylesheet" type="text/css">`
},
ignorePath: path.join(Path.theme, Path.source, 'css')
}
return gulp.src(path.join(Path.layout, '/_partial/head.ejs'))
.pipe(Inject(injectStyle, injectOptions))
.pipe(gulp.dest(path.join(Path.theme, Path.layout, '_partial')))
})
gulp.task('injectScript', ['buildScript'], () => {
const injectScript = gulp.src(path.join(Path.theme, Path.source, '/js/script.js'), {
read: false
})
const injectOptions = {
starttag: '<!-- inject:script -->',
addRootSlash: false,
transform(filePath) {
return `<script src="<%- url_for('js/${filePath}') %>"></script>`
},
ignorePath: path.join(Path.theme, Path.source, 'js')
}
return gulp.src(path.join(Path.layout, '/layout.ejs'))
.pipe(Inject(injectScript, injectOptions))
.pipe(gulp.dest(path.join(Path.theme, Path.layout)))
})
gulp.task('inject', ['injectStyle', 'injectScript'], () => {
return gulp.src([
'!' + path.join(Path.layout, '/layout.ejs'),
'!' + path.join(Path.layout, '/_partial/head.ejs'),
path.join(Path.layout, '/**/*.ejs')
]).pipe(gulp.dest(path.join(Path.theme, Path.layout)))
})
通过这两个任务产生的ejs代码如下:
layout.ejs:
<!-- inject:script -->
<script src="<%- url_for('js/script.js') %>"></script>
<!-- endinject -->
_partial/head.ejs:
<!-- inject:style -->
<link href="<%- url_for('css/style.css') %>" rel="stylesheet" type="text/css">
<!-- endinject -->
- 通过
gulp-watch
监听对应领域的文件, 如果发生了变动就重新生成主题
通过上面四个步骤的构建, 就可以在source/js/
里面编写es6代码了, 开启gulp watch
之后会监听对应模板和scss以及js等文件的变化重新生成主题(用node 子进程进行了hexo clean & hexo g
, 只要等待终端提示即可直接hexo s
查看效果
博客的构建
Hexo博客的构建没什么特别的, 可以参考github上一些优秀的Hexo主题项目的布局格式, 结合Hexo官方文档, 在对应的模板ejs引用对应的Hexo变量实现主题模板的编写即可。关于这个主题的具体构建代码可以看cube-generator
待解决问题
gulp的构建写得还是很乱, 原本的想法是想用
browser-sync
实现修改文件实时刷新的, 但是hexo启动服务器采用的是hexo s
启动, 要先通过hexo g
重新生成public
文件夹才会刷新内容, 所以用browser-sync
的想法也不了了之,后续有时间要把gulp的构建重新写一遍移动端方面做的调试不多, 貌似在一些手机浏览器会出现一些奇怪的问题(我的小米4自带的原生浏览器加载不了用lightgallery读取的图片, 我觉得这个不是我的锅233, 但是有时间还是要看看),highlight.js加载较慢导致手机打开博客页面一开始可以横向滚动(应该是我用了async进行异步的关系)
第三方评论系统只测试了畅言和gitment, disqus因为我这边暂时无法那个(你懂的), 所以这个部分还没写, 很多评论系统都挂了,所以在想是不是要自己也来写个评论系统2333
其他一些奇奇怪怪的问题….