用 webpack 玩转博客园 ⛷
2020-04-27 21:35
274 查看
# 前置
自定义博客园样式需要一下几部分
- 页面定制 CSS 代码
- 博客侧边栏公告(支持 HTML 代码) (支持 JS 代码)
- 页首 HTML 代码
- 页脚 HTML 代码
你可能不熟悉 **页首 HTML 代码** ,可以在此处放入一个 loading,因为页面加载时会最先加载这部分。总之,**页面定制 CSS 代码** 和 **博客侧边栏公告(支持 HTML 代码) (支持 JS 代码)** 是最重要的两部分。
# 方式
自定义你的皮肤可以使用下面这几种方式:
## css in js
通过 webpack 我们可以实现将 css 打包到 js, 样式由 js 动态添加。使用时只需要这样:
1. 引入打包好的 js
2. 给你的皮肤添加一些配置(可选的)
```js
$.awesCnb({
// 给你的皮肤添加一些配置
})
```
> 如果不暴露配置直接引入一个 js 就好了,是不是非常简单?
**缺点**
页面不能及时渲染 css,因为 css in js,但是我们可以加个 loading 解决。 😀
**优点**
这样做甚至可以实现瞬间切换多套皮肤,这里有我以前做的一个例子供您查看。[点击查看切换效果](https://guangzan.gitee.io/imagehost/blog/themechange.gif).
## css && js
上面那样做的缺点很明显, 需要一个 loading, 如果我们将 css 和 js 分离,把 css 放到 **页面定制 CSS 代码**,js 放到 **博客侧边栏公告(支持 HTML 代码) (支持 JS 代码)** 就不会出现这种情况了。通过 webpack plugin `MiniCssExtractPlugin` 可以将皮肤代码分别打包出一个 js 文件和一个 css 文件。
# webpack
如何写一个架子方便开发博客园皮肤呢,下面我把 webpack 配置放出来。
**options.js**
我把需要经常更改的配置单独抽离一个文件,这样做能节省我很多时间。
```js
module.exports = {
themeName: 'reacg',
template: 'post',
eslint: true,
sourceMap: false,
openAnalyzer: false,
cssExtract: false,
}
```
- themeName 创建的主题文件夹名称 (运行 npm start 会启动它)
- template 本地开发要启动的页面 'index' -> 首页 'post' -> 随笔详情页 'tag' -> 标签页 ...
- eslint 是否开启 eslint
- sourceMap 是否开启 sourcemap
- openAnalyzer build 时开启 size 分析
- cssExtract 是否单独抽离 css
`cssExtract` 如果没有开启,build 会打包生成一个 dist, dist 下仅有 js 文件,如上, 这是 css in js 的方式,通过 js 动态添加 `style` ; 如果设为 true ,会在 dist 目录下创建一个 ext 文件夹, 下面放了你的皮肤 js 和 css 文件。
![](https://gitee.com/guangzan/imagehost/raw/master/markdown/awescnb-dist.png)
> 正如你所见, ext 下每一个皮肤对应 js 和 css 两个文件。
**webpack.base.js**
不言而喻, webpack.base.js 是开发环境和生产环境依赖的公共配置。
```js
const path = require('path')
const {themeName, eslint} = require('./options')
const jsLoader = [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
]
if (eslint) {
jsLoader.push({
loader: 'eslint-loader',
options: {
cache: true,
},
})
}
module.exports = {
entry: {
// 多出口
index: './src/main.js',
acg: './src/themes/acg/index.js',
reacg: './src/themes/reacg/index.js',
gshang: './src/themes/gshang/index.js',
element: './src/themes/element/index.js',
[themeName]: `./src/themes/${themeName}/index.js`,
},
output: {
filename: '[name].js',
path: path.join(__dirname, '..', 'dist'),
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: jsLoader,
},
],
},
resolve: {
alias: {
'@': path.resolve('src'),
'@awescnb': path.resolve('src/awescnb'),
'@tools': path.resolve('src/assets/utils/tools'),
'@plugins': path.resolve('src/plugins'),
'@constants': path.resolve('src/constants'),
},
},
}
```
> 这里主要关注多个 entry, 方便打包多个皮肤。
**webpack.dev.js**
开发环境配置
```js
const path = require('path')
const webpack = require('webpack')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {template, themeName, sourceMap} = require('./options')
module.exports = merge(baseWebpackConfig, {
mode: 'development',
devtool: sourceMap ? 'inline-source-map' : '',
devServer: {
host: 'localhost',
port: 8080,
contentBase: path.join(__dirname, 'dist'),
open: true,
hot: true,
disableHostCheck: true,
proxy: {},
before() {},
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: `src/templates/${template}.html`,
inject: 'body',
chunks: [`${themeName}`],
}),
new webpack.HotModuleReplacementPlugin({}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
'postcss-loader',
],
},
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
'postcss-loader',
'sass-loader',
],
},
],
},
})
```
**webpack.prod.js**
```js
const path = require('path')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base')
const {openAnalyzer, cssExtract} = require('./options')
// const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const plugins = [
// new CleanWebpackPlugin()
]
let output = {
filename: '[name].js',
path: path.join(__dirname, '..', 'dist'),
}
let cssLoader = [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
'postcss-loader',
]
let scssLoader = [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
'postcss-loader',
'sass-loader',
]
if (openAnalyzer) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'server',
analyzerHost: '127.0.0.1',
analyzerPort: 8888,
reportFilename: 'report.html',
defaultSizes: 'parsed',
openAnalyzer: true,
generateStatsFile: false,
statsFilename: 'stats.json',
statsOptions: null,
logLevel: 'info',
})
)
}
if (cssExtract) {
output.path = path.join(__dirname, '..', 'dist/ext')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
plugins.push(
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
ignoreOrder: false,
})
)
const MiniCssExtractPluginLoader = {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
hmr: process.env.NODE_ENV === 'development',
},
}
cssLoader[0] = MiniCssExtractPluginLoader
scssLoader[0] = MiniCssExtractPluginLoader
}
module.exports = merge(baseWebpackConfig, {
mode: 'production',
output,
plugins,
externals: {
jquery: 'window.jquery',
},
module: {
rules: [
{
test: /\.css$/,
use: cssLoader,
},
{
test: /\.scss$/,
use: scssLoader,
},
],
},
})
```
通过简单的配置就可以实现任何你想要的结果。webpack 越来越火不是没有原因的啊,快速上手, 生态丰富。如果 cli 用惯了,不如自己尝试打造自己的工作流。如果你没有时间造这个轮子,我已经将他封装好了, 分享给大家。 free to use!可以用它快速地构建、安装、分享你的博客园皮肤。
[![GZ/awescnb](https://gitee.com/guangzan/awescnb/widgets/widget_card.svg?colors=4183c4,ffffff,ffffff,e3e9ed,666666,9b9b9b)](https://gitee.com/guangzan/awescnb)
相关文章推荐
- webpack优化之玩转代码分割和公共代码提取
- 玩转webpack(二):webpack的核心对象
- Vue-router——遇到的坑(一)history模式刷新/设置嵌套路由报错(webpack配置)
- webpack
- 深入学习webpack(二)
- 怎么解决webpack提示“不是内部命令或外部命令”
- vue-webpack 做出来的项目部署到服务器上,点开是空白页(我这里把项目发布到git上)
- 轻松入门React和Webpack
- webpack
- webpack打包的便利工具
- webpack libray 参考例子
- 从头创建一个基于 React, webpack, babel 的模板项目
- 【webpack】——初识
- 详解Web使用webpack构建前端项目
- webpack入门级水坑
- webpack 模块化
- webpack实战
- karma+webpack搭建vue单元测试环境的方法示例
- webpack中的开发环境与生产环境
- 如何使用vue搭建脚手架,nodejs如何进行拉包处理,简述如何基于webpack创建项目模板