您的位置:首页 > 其它

用 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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: