Bootstrap 是一个流行的前端样式库,可以方便快速的构建应用,但默认样式可能不尽人意,本文就介绍如何使用 NPM, Webpack, SASS 针对它的源码来定制自己的主题。版本使用的是 Bootstrap v4.3.1。

本文提供了一个使用此方式编写的一个后台管理模板 Dunwoo Admin,文末有获取源码的方式。演示地址:https://dunwoo.com/projects/dunwoo-admin

安装 Node.js

Webpack 是对前端资源进行打包和编译的工具,它依赖于 Node.js,首先介绍下如何配置和安装绿色版的 Node.js。

下载绿色版本:https://nodejs.org/en/download/ (以 node-v10.16.1-win-x64.zip 为例)

并解压到某个目录下,比如 D:\node-v10.16.1, 然后设置系统环境变量:

NODE_HOME=D:\node-v10.16.1
NODE_PATH=%NODE_HOME%\node_modules
path=增加;%NODE_HOME%;

在 Node.js 主目录新建 node_global 和 node_cache 两个目录,并使用以下命令设置 npm 全局安装模块的位置以及下载缓存路径:

npm config set prefix "D:\node-v10.16.1\node_global"
npm config set cache "D:\node-v10.16.1\node_cache"

最后,可以在命令行使用 node -v 和 npm -v 验证是否安装成功。

Webpack 安装和配置

安装 Webpack 之前,需要使用 npm init 在项目根目录生成一个 package.json 文件,它类似 Java 中 Maven 的 pom.xml, 用于描述项目的元信息,名称、版本等,更重要的是它指定了项目运行依赖的模块,下面就是本项目此文件的内容:

{
"name": "dunwoo-admin",
"version": "1.0.0",
"description": "Bootstrap 4 Theme",
"author": "wskwbog",
"license": "MIT",
"private": true,
"keywords": [],
"scripts": {
"build": "webpack --progress --colors",
"dev": "webpack-dev-server --inline --devtool eval-source-map --progress",
"start": "npm run dev"
},
"devDependencies": {
"@babel/core": "^7.2.2",
"@babel/plugin-proposal-object-rest-spread": "^7.3.2",
"@babel/preset-env": "^7.3.1",
"autoprefixer": "^9.4.7",
"babel-loader": "^8.0.6",
"css-loader": "^3.2.0",
"node-sass": "^4.12.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^7.2.0",
"style-loader": "^1.0.0",
"webpack": "^4.39.2",
"webpack-cli": "^3.3.7",
"webpack-dev-server": "^3.8.0",
"mini-css-extract-plugin": "^0.8.0",
"clean-webpack-plugin": "^3.0.0"
},
"dependencies": {
"bootstrap": "^4.3.1",
"jquery": "^3.3.1",
"popper.js": "^1.14.7"
}
}

其中关键配置的意义是:

  • scripts: 配置不同功能脚本命令的缩写,可以使用 npm run build|dev 简单方便的调用
  • devDependencies: 指定项目开发所需要的模块
  • dependencies: 指定项目运行所依赖的模块

配置好 package.json 后就可以在当前目录运行 npm install 依赖的模块就会下载到当前目录的 node_modules 目录中。

在开始使用 Webpack 之前,还要进行一些配置,这也是比较麻烦的地方,本项目的 webpack.config.js 配置内容如下:

// 引入 node 相关模块
const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = {
mode: 'development',
devtool: 'source-map',
entry: {
theme: './src/js/theme.js' // 入口文件
},
output: { // 打包输出目录
path: path.resolve(__dirname, './dist/'),
filename: 'js/[name].js'
},
devServer: { // 本地开发服务器
contentBase: './dist/',
host: '0.0.0.0',
port: 3000,
writeToDisk: true
},
module: {
rules: [{
test: /(\.jsx|\.js)$/, // 正则匹配 .jsx 或 .js 后缀的文件
loader: 'babel-loader',
exclude: /node_modules/
}, {
test: /\.(scss)$/, // 正则匹配 .scss 后缀的文件
use: [{
// loader: 'style-loader', // inject CSS to page
loader: MiniCssExtractPlugin.loader,
options: {
// publicPath: '../',
// hmr: process.env.NODE_ENV === 'development',
},
}, {
loader: 'css-loader', // translates CSS into CommonJS modules
}, {
loader: 'postcss-loader', // Run postcss actions
options: {
plugins: function () { // postcss plugins, can be exported to postcss.config.js
return [
require('autoprefixer')
];
}
}
}, {
loader: 'sass-loader' // compiles Sass to CSS
}]
}]
},
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns:['js/*', 'css/*']
}),
new MiniCssExtractPlugin({
filename: 'css/[name].css',
chunkFilename: 'css/[id].css',
})
]
}

接下来分析下各配置项的作用。

entry/output

entry: {
theme: './src/js/theme.js'
},
output: {
path: path.resolve(__dirname, './dist/'),
filename: 'js/[name].js'
},

入口(entry)和出口(output)的配置比较简单,指定了从哪个模块开始构建以及将编译结果输出目的地。其中 __dirname 表示 webpack.config.js 所在的目录。

webpack-dev-server

通常开发的过程是:

  1. 修改 scss 样式
  2. 然后命令行运行 npm run build 编译
  3. 最后刷新页面看效果

这几步完全可以自动化,Webpack 就提供了一个本地开发 Web 服务器 webpack-dev-server, 它可以监听代码的改动并自动编译和发布,基本配置如下:

devServer: {
contentBase: './dist/', // 资源根目录
host: '127.0.0.1', // 绑定主机 IP
port: 3000, // 监听端口
writeToDisk: true // 将编译结果写到磁盘
},

更多配置项可参考:https://webpack.js.org/configuration/dev-server/

接下来就是 Webpack 两个比较重要概念的配置, Loader 和 Plugin:

  • Loader: 编译和转换模块源码,比如将 scss 编译成 css, 将 ES6 转为 JS, 将 JSX 文件转成 JS 文件等等
  • Plugin: 用于解决 Loader 无法实现的功能,比如清理,打包优化和压缩等等

Babel

Bootstrap 4 使用 ES6 重写了所有的 JS 组件,而 Babel 就是一个 JavaScript 编译器,它可以将使用 ES6 语法编写的文件,转成浏览器兼容的 JS 文件。在 package.json 中与它相关的模块如下:

  • @babel/core: Babel 编译的核心
  • @babel/preset-env: 为每个环境预设的 Babel
  • babel-loader: 结合使用 Babel 和 webpack 编译 JavaScript
  • @babel/plugin-proposal-object-rest-spread: 支持 ES6 扩展运算符(...)

与把它相关的配置文件通常会放到一个名为 .babelrc.js 的文件中:

module.exports = {
presets: [
[
'@babel/env',
{
loose: true,
modules: false,
exclude: ['transform-typeof-symbol']
}
]
],
plugins: [
'@babel/plugin-proposal-object-rest-spread'
]
};

CSS 模块

Webpack 提供了两个 Loader 来处理样式,css-loaderstyle-loader,二者处理的任务不同:

  • css-loader: 解析 @import 和 url() 方法,实现类似 import/require() 的功能
  • style-loader: 将样式加入到页面中,与 css-loader 结合使用可以把样式嵌入到 webpack 打包后的 JS 文件中

CSS 预处理器比如 Sass 对原生 CSS 进行了扩展,添加了变量,函数等特性,使得 css 的编写更加灵活,Webpack 配置以下两个 Loader 后就能直接使用:

  • sass-loader: 将 scss 编译成 css
  • postcss-loader: 主要使用 autoprefixer 添加浏览器前缀

具体配置可查看上文的 webpack.config.js, 有一点需要注意的是: 高版本的 autoprefixer, 支持的浏览器配置通常放在 .browserslistrc 文件中。

mini-css-extract-plugin

将 CSS 提取为独立文件的插件,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,支持 CSS 和 SourceMaps 的按需加载,依赖 Webpack 4 以上的版本。

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// 指定资源路径, 默认与 webpackOptions.output 相等
publicPath: '../',
// 模块热加载相关配置
hmr: process.env.NODE_ENV === 'development',
},
},
'css-loader',
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// all options are optional
filename: '[name].css',
chunkFilename: '[id].css',
ignoreOrder: false, // Enable to remove warnings about conflicting order
}),
],
};

更多配置项可参考:https://webpack.js.org/plugins/mini-css-extract-plugin/

clean-webpack-plugin

Webpack 构建之前用于删除和清理构建文件夹的插件,这个插件有个属性 cleanOnceBeforeBuildPatterns 可以配置哪些文件和文件夹要删除,哪些不删除,一个简单的示例如下:

const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin({ // 只清理 js 和 css 目录中的文件
cleanOnceBeforeBuildPatterns:['js/*', 'css/*']
}),
],
};

更多配置项可参考:https://www.npmjs.com/package/clean-webpack-plugin

Bootstrap 主题定制方法

定制 Bootstrap 4 主题有两个方法,一是直接修改源码,但这样后续不好升级;二是修改它提供的 SCSS 变量灵活定制,这样对源码没有侵入性,可以在不触及核心文件的情况下完全重新设计 Bootstrap 4 的样式。项目文件的基本结构如下:

dunwoo-admin/
├── .babelrc.js
├── .browserslistrc
├── .gitignore
├── package.json
├── webpack.config.js
├── README.md
├── src/
│ ├── scss/
│ │ ├── base/
│ │ ├── pages/
│ │ ├── partials/
│ │ ├── utilities/
│ │ ├── vendor/
│ │ └── _theme.scss
│ ├── js/
│ │ ├── modules/
│ │ ├── vendor/
│ │ └── theme.js
│ │── fonts/
│ └── img/
└── dist/
├── css/
│ └── theme.css
├── js/
│ └── theme.js
├── img/
├── fonts/
└── libs/

其中主要的 Sass 文件就是 src/scss/_theme.scss:

@charset "utf-8";
// 覆盖原设计样式的变量
@import "base/variables-theme";
// bootstrap 核心源码
@import "../../node_modules/bootstrap/scss/bootstrap";
// 自定义组件的样式
@import "base/variables";
@import "base/general"; @import "partials/menubar";
@import "partials/navbar";
@import "partials/card";
@import "partials/widget";
@import "partials/timeline"; @import "pages/signin"; @import "utilities/utilities";

一个简单修改主题颜色变量的方法是:

$theme-colors: (
"primary": #2c7be5,
"secondary": #95aac9,
"success": #00d97e,
"info": #39afd1,
"warning": #f6c343,
"danger": #e63757,
"light": #f8f9fa,
"dark": #3b506c
);

在项目根目录执行 npm run build 就能在页面看到修改结果。

小结

本文只是对 webpack 简单的使用,对于前端目前也正在学习,如有错误欢迎指出交流。

源码可从 GitHub 链接下载,https://github.com/dwosc/dunwoo-admin

或者关注微信公众号「顿悟源码」回复关键词「Bootstrap」 获取百度网盘下载链接。

主题将会不断更新优化,欢迎关注!

Bootstrap4默认样式不对胃口?教你使用NPM+Webpack+SASS来定制的更多相关文章

  1. CSS 重置默认样式

    1. 概述 1.1 说明 css重置样式主要是为了让各个浏览器的CSS样式有一个统一的基准,使HTML元素样式在跨浏览器时有一致性的效果. 备注:浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的 ...

  2. 取消chrome浏览器下input和textarea的默认样式;html5默认input内容清除“×”按钮去除办法

    取消chrome浏览器下input和textarea的默认样式: outline:none;/*清空chrome中input的外边框*/ html5默认input内容清除“×”按钮去除办法: inpu ...

  3. 用纯css改变下拉列表select框的默认样式(不兼容IE10以下)

    在这篇文章里,我将介绍如何不依赖JavaScript用纯css来改变下拉列表框的样式.     事情是这样的,您的设计师团队向您发送一个新的PSD(Photoshop文档),它是一个新的网站的最终设计 ...

  4. CSS3初学篇章_7(布局/浏览器默认样式重置)

    CSS布局说到布局,就不得不提布局的核心<div>标签,它与其它标签一样,也是一个XHTML所支持的标签,专门用于布局设计的容器标签.在css布局方式中,div 是这种布局方式的核心对象, ...

  5. 用纯css改变下拉列表select框的默认样式

    http://ourjs.com/detail/551b9b0529c8d81960000007 在这篇文章里,我将介绍如何不依赖JavaScript用纯css来改变下拉列表框的样式. 问题的提出 事 ...

  6. css知多少(4)——解读浏览器默认样式

    上一节<css知多少(3)——样式来源与层叠规则>介绍了样式的五种来源,咱们再通过一张图回顾一下. 对于上面的三层,咱们大概都比较熟悉了.下面的两层中,用户自定义样式一般也就是改一改字号大 ...

  7. 浏览器默认样式(user agent stylesheet)+cssreset

    每种浏览器都有一套默认的样式表,即user agent stylesheet,在写网页时,没有指定的样式,按浏览器内置的样式表来渲染.这是合理的,像word中也有一些预留样式,可以让我们的排版更美观整 ...

  8. 使用 CSS 去掉 iPhone 网页上按钮的超大圆角以及文本框圆角默认样式

    使用 iPhone 上的浏览器去浏览网页的时候,按钮总是显示超大圆角且颜色由上而下渐变的样式,显得超级恶心,而且文本框也会有一定的圆角,但是我们自己定义 border-radius 也没有效果,经过搜 ...

  9. ios html5 网页取消默认样式

    ios的的默认样式修改成扁平化的样式 重要的一句css  -webkit-appearance: none;  将样式清除 单数会出现将raido的选择按钮也会消失 所以需要对radio的样式进行重新 ...

随机推荐

  1. 想成为顶尖 Java 程序员?请先过了下面这些技术问题。

    一.数据结构与算法基础 说一下几种常见的排序算法和分别的复杂度. 用Java写一个冒泡排序算法 描述一下链式存储结构. 如何遍历一棵二叉树? 倒排一个LinkedList. 用Java写一个递归遍历目 ...

  2. 深扒JVM,对它进行“开膛破肚”式解析!

    1. 打怪升级,你绕不开JVM JVM,对Java程序员进阶而言,是一个绝对绕不开,也不能绕开的话题. 在你打怪升级.进阶蜕变的路上,势必会遇到项目上线中各种OOM.GC等问题,此时JVM的功底就至关 ...

  3. ecshop 管理后台菜单及权限管理机制

    ecshop 所有的一级菜单选项存放于languages\zh_cn\admin\common.php 文件里面,使用 $_LANG['02_cat_and_goods'] = '商品管理';  这样 ...

  4. 深入理解 linux磁盘顺序写、随机写

    一.前言 ● 随机写会导致磁头不停地换道,造成效率的极大降低:顺序写磁头几乎不用换道,或者换道的时间很短 ● 本文来讨论一下两者具体的差别以及相应的内核调用 二.环境准备 组件 版本 OS Ubunt ...

  5. 洛谷 P2044 [NOI2012]随机数生成器

    题意简述 读入X[0], m, a, c, n和g $ X[n+1]=(a*X[n]+c)\mod m $ 求X数列的第n项对g取余的值. 题解思路 矩阵加速 设\[ F=\begin{bmatrix ...

  6. html5新特性-header,nav,footer,aside,article,section等各元素的详解

    Html5新增了27个元素,废弃了16个元素,根据现有的标准规范,把HTML5的元素按优先级定义为结构性属性.级块性元素.行内语义性元素和交互性元素四大类. 下面是对各标签的详解,section.he ...

  7. c# oracle 数据库连接以及参数化查询

    private string OracleSearchDemo(string cadqueueId) { string address = null; using (OracleConnection ...

  8. 最大层内元素和----leetcode周赛150_1002

    题目描述: 给你一个二叉树的根节点 root.设根节点位于二叉树的第 1 层,而根节点的子节点位于第 2 层,依此类推. 请你找出层内元素之和 最大 的那几层(可能只有一层)的层号,并返回其中 最小 ...

  9. 并查集(不相交集合)详解与java实现

    目录 认识并查集 并查集解析 基本思想 如何查看a,b是否在一个集合? a,b合并,究竟是a的祖先合并在b的祖先上,还是b的祖先合并在a上? 其他路径压缩? 代码实现 结语 @(文章目录) 认识并查集 ...

  10. redux 源码阅读

    目录 [目录结构] [utils] actionTypes.js isPlainObject.js warning.js [逻辑代码] index.js createStore.js compose. ...