在上一篇文章中我给大家分享了预处理器(loader),里面讲到了style-loader 和css-loader,有关样式引入的问题,但是上面的样式文件只是引入到style标签里面,并不是我想要的样式文件独立分离。

如果想了解有关css-loader和style-loader可以参考以下地址:

Webpack实战(四):教教你如何轻松搞定-预处理器(loader)

通过js引入样式文件只是把样式添加到style标签内,而不是引入一个独立的css文件,一般来说,在生产环境下,我们希望样式存在于CSS文件中而不是style标签中,因为文件更有利于客户端进行缓存。

Webpack社区有专门的插件:extract-text-webpack-plugin(适用于Webpack 4之前版本)和mini-css-extract-plugin(适用于Webpack 4及以上版本),它们就是专门用于提取样式到CSS文件的。

  1. extract-text-webpack-plugin

    extract-text-webpack-plugin安装命令代码如下:
# for webpack 3
npm install --save-dev extract-text-webpack-plugin
# for webpack 2
npm install --save-dev extract-text-webpack-plugin@2.1.2
# for webpack 1
npm install --save-dev extract-text-webpack-plugin@1.0.1

由于webpack版本不一样,extract-text-webpack-plugin安装的出来版本的也不一样。

配置代码如下:

const ExtractTextPlugin = require("extract-text-webpack-plugin");
const path = require('path')
module.exports = {
context: path.join(__dirname, './src'),
entry: {
index: './index.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'index.js'
},
mode: 'development',
module: {
rules: [
{
test: /\.css$/i,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
}),
exclude: /node_modules/
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: [
[
'env', {
modules: false
}
]
]
}
}
}
],
},
plugins: [
new ExtractTextPlugin("styles.css") //提取后css文件名称
]
}

在module.rules中我们设置了处理CSS文件和js文件的规则,其中css配置的use字段并没有直接传入loader,而是使用了插件的extract方法包了一层。内部的fallback属性用于指定当插件无法提取样式时所采用的loader,use(extract方法里面的)用于指定在提取样式之前采用哪些loader来预先进行处理。除此之外,还要在Webpack的plugins配置中添加该插件,并传入提取后的资源文件名。

由于我电脑项目里装的4.0以上的webpack版本,这里不再做打包测试。

样式的提取是以资源入口开始的整个chunk为单位的。比如我们的应用从index.js开始引入了几百个模块,这些模块都引入了它们各自的样式文件,但是最终生成的c s s文件只有一个,因为它们都来自同一个入口模块。上面我们讲styles.css作为文件名传给extract-text-webpack-plugin,但是当项目有多个入口的时候就会发生重名问题。就像我们前面动态配置的output.filename一样。这里我们也将要对插件提取的css文件使用类似模版的命名方式。

下面是入口的index.js和about.js

// index.js
import './index.css' // about.js
import './about.css'

we bpack.config.js配置部分代码如下

const ExtractTextPlugin = require("extract-text-webpack-plugin");
const path = require('path')
module.exports = {
context: path.join(__dirname, './src'),
entry: {
index: './index.js',
about: './about.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
mode: 'development',
module: {
rules: [
{
test: /\.css$/i,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
}),
exclude: /node_modules/
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: [
[
'env', {
modules: false
}
]
]
}
}
}
],
},
plugins: [
new ExtractTextPlugin("[name].css") //提取后css文件名称
]
}

我们使用[name].css来动态生成c s s文件名,name为即entry中我们为每一个入口分配的名字(index、about),由此可以推出[name]指的是chunk(chunk是对一组有依赖关系的模块的封装)的名字。

  1. mini-css-extract-plugin

    mini-css-extract-plugin 是 extract-text-webpack-plugin的升级版本,它拥有更多的特性和更好的性能。最突出的一条就是 mini-css-extract-plugin支持按需加载css,举个例子,a.js通过import()函数异步加载了b.js,b.js里面加载了style.css,那么style.css最终只能被同步加载(通过HTML的link标签)。但是现在mini-css-extract-plugin会单独打包出一个0.css(假设使用默认配置),这个CSS文件将由a.js通过动态插入link标签的方式加载。

    首先安装mini-css-extract-plugin
npm install --save-dev mini-css-extract-plugin

下面是入口的index.js和index2.js

// index.js
import './common.css' // index2.js
import './style.css'

web pack.config.js配置如下:

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
context: path.join(__dirname, './src'),
entry: {
index: './index.js',
index2: './index2.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
mode: 'development',
module: {
rules: [
{
test: /\.css$/i,
use: [{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
},
}, 'css-loader'],
exclude: /node_modules/
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: [
[
'env', {
modules: false
}
]
]
}
}
}
],
},
plugins: [new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
})],
}

打包效果如下:



可以发现最后输出两个c s s文件名分别为chunk 名,index.css,index2.css

在配置上mini-css-extract-plugin与extract-text-webpack-plugin有以下几点不同

  • loader规则设置的形式不同,并且mini-css-extract-plugin支持配置publicPath,用来指定异步CSS的加载路径。
  • 不需要设置fallback。
  • 在plugins设置中,除了指定同步加载的CSS资源名(filename),还要指定异步加载的CSS资源名(chunkFilename)。

总结

Webpack样式文件分离,主要用两个插件mini-css-extract-plugin与extract-text-webpack-plugin,它们有着各自的特点,但是如果webpack版本4.0以上建议用mini-css-extract-plugin,它拥有更多的特性,特别是按需加载cs s,解决了一些性能问题。

如果想了解更多,请扫描二维码:

Webpack实战(五):轻松读懂Webpack如何分离样式文件的更多相关文章

  1. 轻松读懂IL

    轻松读懂IL先说说学IL有什么用,有人可能觉得这玩意平常写代码又用不上,学了有个卵用.到底有没有卵用呢,暂且也不说什么学了可以看看一些语法糖的实现,或对.net理解更深一点这些虚头巴脑的东西.最重要的 ...

  2. C#基础之IL ,轻松读懂中间代码IL 转载

    [No0000152]C#基础之IL,轻松读懂IL   先说说学IL有什么用,有人可能觉得这玩意平常写代码又用不上,学了有个卵用.到底有没有卵用呢,暂且也不说什么学了可以看看一些语法糖的实现,或对.n ...

  3. 五分钟读懂UML类图

    平时阅读一些远吗分析类文章或是设计应用架构时没少与UML类图打交道.实际上,UML类图中最常用到的元素五分钟就能掌握,下面赶紧来一起认识一下它吧: 一.类的属性的表示方式 在UML类图中,类使用包含类 ...

  4. 五分钟读懂UML类图(转)

    平时阅读一些远吗分析类文章或是设计应用架构时没少与UML类图打交道.实际上,UML类图中最常用到的元素五分钟就能掌握,下面赶紧来一起认识一下它吧: 一.类的属性的表示方式 在UML类图中,类使用包含类 ...

  5. 五分钟读懂UML类图(转)

    平时阅读一些远吗分析类文章或是设计应用架构时没少与UML类图打交道.实际上,UML类图中最常用到的元素五分钟就能掌握,下面赶紧来一起认识一下它吧: 一.类的属性的表示方式 在UML类图中,类使用包含类 ...

  6. Webpack实战(一):Webpack打包工具安装及参数配置

    为什么要模块化 javascript跟其他开发语言有很多的区别,其中一个就是没有模块化概念,如果一个项目中有多个js文件,我们只能通过script标签引入的方式,把一个个js文件插入到页面,这种做法会 ...

  7. (23/24) webpack实战技巧:如何在webpack环境中使用Json

    在webpack1或者webpack2版本中,若想在webpack环境中加载Json文件,则需要加载一个json-loader的loader进来的.但是在webpack3.x版本中,则不需要在另外引入 ...

  8. (18/24) webpack实战技巧:快速入门webpack模块化配置

    搞个小例子便于学习: 具体操作为把上节中的webpack.config.js中的entry入口文件进行模块化设置,单独拿出来制作成一个模块. 1.在根目录新建一个config文件,然后新建webpac ...

  9. 30分钟?不需要,轻松读懂IL

    先说说学IL有什么用,有人可能觉得这玩意平常写代码又用不上,学了有个卵用.到底有没有卵用呢,暂且也不说什么学了可以看看一些语法糖的实现,或对.net理解更深一点这些虚头巴脑的东西.最重要的理由就是一个 ...

随机推荐

  1. H3C 以跳数评估的路由并非最优路径

  2. UVA 437 "The Tower of Babylon" (DAG上的动态规划)

    传送门 题意 有 n 种立方体,每种都有无穷多个. 要求选一些立方体摞成一根尽量高的柱子(在摞的时候可以自行选择哪一条边作为高): 立方体 a 可以放在立方体 b 上方的前提条件是立方体 a 的底面长 ...

  3. 2018-2-13-win10-UWP-Markdown-含源代码

    title author date CreateTime categories win10 UWP Markdown 含源代码 lindexi 2018-2-13 17:23:3 +0800 2018 ...

  4. Linux 内核释放函数和 kobject 类型

    讨论中仍然缺失的一个重要事情是当一个 kobject 的引用计数到 0 时会发生什么. 创建 kobject 的代码通常不知道什么时候要发生这个情况; 如果它知道, 在第一位使用一个引 用计数就没有意 ...

  5. Javascript 防扒站,防止镜像网站

    自己没日没夜敲出来的站,稍微漂亮一点,被人看上了就难逃一扒,扒站是难免的,但不能让他轻轻松松就扒了: 前些天有个朋友做的官网被某不法网站镜像,严重影响到 SEO,当时的解决方法是通过屏蔽目标 IP 来 ...

  6. Vue+node.js实现一个简洁的个人博客系统

    本项目是一个用vue和node以及mysql实现的一个简单的个人博客系统,整体逻辑比较简单.但是可以我们完整的了解一个项目从数据库到后端到前端的实现过程,适合不太懂这一块的朋友们拿来练手. 本项目所用 ...

  7. Servlet 会话

    在网络的七层模型中,会话层位于传输层之上,它定义如何开始.控制和结束一个会话.七层模式目前仅仅处于理论阶段,但是Web中借鉴了其中的一些思路.在Web中浏览器第一次发送请求到服务器开始直到一方断开为止 ...

  8. boostrap-非常好用但是容易让人忽略的地方【4】:Font Awesome

    font-awesome基本用法 官方代码传送门 font-awesome在bootstrap中的特殊用法(这个才是重点) 要点归纳1(官方) 官方代码传送门 要点归纳2(我的) <a href ...

  9. boostrap-非常好用但是容易让人忽略的地方【3】:clearfix

    代码 显示结果 代码 结果

  10. HDU 2102 A计划 DFS与BFS两种写法 [搜索]

    1.题意:一位公主被困在迷宫里,一位勇士前去营救,迷宫为两层,规模为N*M,迷宫入口为(0,0,0),公主的位置用'P'标记:迷宫内,'.'表示空地,'*'表示墙,特殊的,'#'表示时空传输机,走到这 ...