原文地址:https://github.com/zhengweikeng/blog/issues/9

我们可以在js中引入样式文件

require('myStyle.css')

这时我们便需要引入相应的webpack loader来帮助我们解析这段代码。

一般来说需要引入css-loader和style-loader,其中css-loader用于解析,而style-loader则将解析后的样式嵌入js代码。

// webpack配置如下
{
module: {
loaders: [
{ test: /\.$/, loader: "style-loader!css-loader" }
]
}
}

可以发现,webpack的loader的配置是从右往左的,从上面代码看的话,就是先使用css-loader之后使用style-loader。

同理,如果你使用less来写样式的话,则需要先用less-loader来编译样式文件为css文件,再继续使用css-loader与style-loader。

{
module: {
loaders: [
{ test: /\.$/, loader: "style-loader!css-loader!less-loader" }
]
}
}

我们知道,webpack配置loader时是可以不写loader的后缀明-loader,因此css-loader可以写为css。

将样式抽取出来为独立的文件

将require引入的样式嵌入js文件中,有好处也有坏处。好处是减少了请求数,坏处也很明显,就是当你的样式文件很大时,造成编译的js文件也很大。

我们可以使用插件的方式,将样式抽取成独立的文件。使用的插件就是extract-text-webpack-plugin

基本用法如下

var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
module: {
loaders: [
{ test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader") }
]
},
plugins: [
new ExtractTextPlugin("styles.css")
]
}

根据插件在github上的解释,ExtractTextPlugin.extract可以有三个参数。

第一个参数是可选参数,传入一个loader,当css样式没有被抽取的时候可以使用该loader。

第二个参数则是用于编译解析的css文件loader,很明显这个是必须传入的,就像上述例子的css-loader。

第三个参数是一些额外的备选项,貌似目前只有传入publicPath,用于当前loader的路径。

那什么时候需要传入第一个参数呢,那就得明白什么时候样式不会被抽取出来。

了解过code splittiog的同学便会知道,我们有些代码在加载页面的时候不会被使用时,使用code splitting,可以实现将这部分不会使用的代码分离出去,独立成一个单独的文件,实现按需加载。

那么如果在这些分离出去的代码中如果有使用require引入样式文件,那么使用ExtractTextPlugin这部分样式代码是不会被抽取出来的。

这部分不会抽取出来的代码,可以使用loader做一些处理,这就是ExtractTextPlugin.extract第一个参数的作用。

根据上面的案例,ExtractTextPlugin需要配合plugin使用。

new ExtractTextPlugin([id: string], filename: string, [options])
  1. 该插件实例的唯一标志,一般是不会传的,其自己会生成。
  2. 文件名。可以是[name]、[id]、[contenthash]
    [name]:将会和entry中的chunk的名字一致
    [id]:将会和entry中的chunk的id一致
    [contenthash]:根据内容生成hash值
  3. options
    allchunk: 是否将所有额外的chunk都压缩成一个文件
    disable:禁止使用插件

这里的参数filename里如何理解呢?上述案例指定了一个固定的名字,因此便会生成一个styles.css文件。

那么像[name]、[id]这些如何理解。这个在你有多个entry的时候,便需要使用这种方式来命名。

var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: {
"script": "./src/entry.js",
"bundle": "./src/entry2.js",
},
...
module: {
loaders: [
{ test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader") }
]
},
plugins: [
new ExtractTextPlugin("[name].css")
]
}

这时候便会生成两个css文件,一个是script.css,另一个便是bundle.css。那些[id]、[contenthash]也是一个道理。

只要明白,在你有多个entry是,一定要使用这种方式来命名css文件。

最后还有那个allchunks又是什么呢?很简单,还记得前面提到的code splitting么?将该参数配置为true,那么所有分离文件的样式也会全部压缩到一个文件上。

plugins: [
new ExtractTextPlugin("[name].css", {allChunks: true})
]

postcss

以前我们写样式时,有些样式不同浏览器需要加不同的前缀,如-webkit-。现在有了构建工具,我们便不需要再去关注这些前缀了,构建工具会自动帮我们加上这些前缀。

对于webpack我们自然想到需要使用loader或者plugin来帮助我们做这些事情,查了下发现autoprefixer-loader已经废弃不再维护了,推荐使用posscss

postcss是用于在js中转换css样式的js插件,需要搭配其他插件一起使用,这点和babel6一样,本身只是个转换器,并不提供代码解析功能。

这里我们需要autoprefixer插件来为我们的样式添加前缀。首先下载该模块。

npm install autoprefixer --save-dev

接着便可以配置webpack了

var autoprefixer = require('autoprefixer')
module.exports = {
...
module: {
loaders: [
...
{
{
test: /\.css$/,
loader: ExtractTextPlugin.extract(["css-loader", "postcss-loader"])
},
}
]
},
postcss: [autoprefixer()],
...
}

查看一下抽取出来的样式文件便可以发现已经加上了前缀

a {
display: flex;
}
/*compiles to:*/
a {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex
}

另外autoprefixer还可以根据目标浏览器版本生成不同的前缀个数,例如你的应用的使用用户如果大多数是使用比较新版本的浏览器,那么便可以做如下配置。

postcss: [autoprefixer({ browsers: ['last 2 versions'] })]

这是生成的样式便会有些不一样,还是上面的例子

a {
display: flex;
}
/*compiles to:*/
a {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}

postcss后记

这里再说一个问题,有些童鞋可能会在css文件中使用@import引入其他样式文件,但是使用autoprefixer发现,import进来的样式没有处理,如下面所示:

/*myStyle.css:*/
body {
background-color: gray;
}
.flex {
display: flex;
} /*myStyle2.css:*/
@import "./myStyle.css";
.div {
color: red;
} /*autoprefixer之后*/
body {
background-color: gray;
}
.flex {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
body {
background-color: gray;
}
.flex {
display: flex;
}
.div {
color: red;
}

要解决这个问题,postcss有个解释,它让我们使用postcss-import插件,再配合autoprefixer

postcss: function(webpack) {
return [
postcssImport({
addDependencyTo: webpack
}),
autoprefixer
]
},

其实我们是不推荐使用@import的,心细的童鞋可以看到最后生成的样式文件有样式是重复的。

所以一般我们应该是在js中使用require来引入样式文件。可以参考的说法这里

样式压缩

压缩代码我们可以使用webpack的内置插件UglifyJsPlugin来做,它既可以压缩js代码也可以压缩css代码。

plugins: [
...
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
...
]

其实并不能说是在压缩css代码,本质来说还是压缩js代码,再将这块代码输出到css文件中。

使用CommonsChunkPlugin抽取公共代码

首先要明确一点CommonsChunkPlugin是在有多个entry时使用的,即在有多个入口文件时,这些入口文件可能会有一些共同的代码,我们便可以将这些共同的代码抽取出来成独立的文件。明白这一点非常重要。(搞了很久才明白的一点,唉~~~~)

如果在多个entry中require了相同的css文件,我们便可以使用CommonsChunkPlugin来将这些共同的样式文件抽取出来为独立的样式文件。

module.exports = {
entry: {
"A": "./src/entry.js",
"B": "./src/entry2.js"
},
...
plugins: [
new webpack.optimize.CommonsChunkPlugin({name: "commons", filename: "commons.js"}),
...
]
}

当然,这里不止会抽取共同的css,如果有共同的js代码,也会抽取成为commons.js。

这里有个有趣的现象,抽取出来的css文件的命名将会是参数中name的值,而js文件名则会是filename的值。

CommonsChunkPlugin好像只会将所有chunk中都共有的模块抽取出来,如果存在如下的依赖

// entry1.js
var style1 = require('./style/myStyle.css')
var style2 = require('./style/style.css') // entry2.js
require("./style/myStyle.css")
require("./style/myStyle2.css") // entry3.js
require("./style/myStyle2.css")

使用插件后会发现,根本没有生成commons.css文件。

如果我们只需要取前两个chunk的共同代码,我们可以这么做

module.exports = {
entry: {
"A": "./src/entry.js",
"B": "./src/entry2.js",
"C": "./src/entry3.js"
},
...
plugins: [
new webpack.optimize.CommonsChunkPlugin({name: "commons", filename: "commons.js", chunks: ['A', 'B']}),
...
]
}

补充一下

根据webpack官网中关于stylesheet的说法,建议是不要将allChunks设为true,即只是将样式嵌入到分离文件中。

这个可能还是需要具体问题具体分析了。

webpack对样式的处理的更多相关文章

  1. webpack 打包样式资源

    webpack 打包样式资源 webpack.config.js配置文件内容为: // 用来拼接绝对路径的方法 const {resolve} = require('path') module.exp ...

  2. 【webpack】-- 样式加载

    加载css需要用到css-loader和style-loader css-loader将@import 和 url 处理成正规的ES6 import ,如果@import指向的是一个外部资源,css- ...

  3. [vue]webpack使用样式

    webpack: 使用自己写样式 main.js导入全局生效 import Vue from 'vue' import App from './App.vue' import './index.css ...

  4. webpack打包样式代码去重

    一.问题描述 控制台审查样式,同一个样式被导入很多遍,每调用一次@import "common.less";打包时都会多出一份类似的样式代码. 二.问题分析 补上... 三.解决方 ...

  5. Vue系列之 => webpack处理样式文件

    处理css文件 安装 npm i style-loader css-loader -D main.js import $ from 'jquery' //Es6中导入模块的方式 import './c ...

  6. Webpack干货系列 | 怎么运用 Webpack 5 处理css/scss/sass、less、stylus样式资源

    程序员优雅哥简介:十年程序员,呆过央企外企私企,做过前端后端架构.分享vue.Java等前后端技术和架构. 本文摘要:主要讲解webpack 5 如何高效处理CSS 资源.scss/sass 资源.l ...

  7. Webpack 速成

    前言 如果你已经对Webpack精通了或者至少一直在工作中使用它,请关闭当前浏览器标签,无视这篇文章. 这篇文章本意是写给我自己看的,作为一篇Cookbook供快速查询和上手用.原因是虽然工作中会涉及 ...

  8. webpack问题列表及解决方案

    1.提升webpack打包速度 2.cssloader顺序有先后 3.如何正确引用图片 4.打包后访问不到json文件 5.打包后如何访问项目 6.打包后的文件 7.为什么执行webpack,就可以打 ...

  9. Webpack+Vue+ES6 前端组件化开发mobile-multi-page应用实战总结和踩坑

    本文版权归博客园和作者吴双本人共同所有 转载和爬虫请注明原文地址 www.cnblogs.com/tdws 一.写在前面 项目上线有一段时间了,一个基于webpack+vue+ES6的手机端多页面应用 ...

随机推荐

  1. WF4.0 自定义CodeActivity与Bookmark<第三篇>

    一.自定义CodeActivity CodeActivity用于自定义一段代码,可实现你自己写的任意功能. 要注意的有两点: 1.自定义CodeActivity必须继承自CodeActivity; 2 ...

  2. OpenLDAP 安装及配置 笔记

    首先下载 OpenLdap(Ldap服务器) 和 LdapAdmin(客户端) 两个软件 OpenLDAPforWindows_2.4.39.part1.rar OpenLDAPforWindows_ ...

  3. Android IOS WebRTC 音视频开发总结(五十)-- 技术服务如何定价?

    这篇文章最早是杜老师写的,看完感触很深,加上之前跟咨询公司的朋友也讨论过这方面的问题,所以结合自己的经验,做了些删改(得到了杜老师的授权). 先通过下面几个简单的问题来了解技术服务: 问题1:技术服务 ...

  4. A Neural Probabilistic Language Model

    A Neural Probabilistic Language Model,这篇论文是Begio等人在2003年发表的,可以说是词表示的鼻祖.在这里给出简要的译文 A Neural Probabili ...

  5. 解决Android sdk更新不能下载或下载内容过慢

    Android Android SDK 配置步骤 启动 Android SDK Manager ,打开主界面,依次选择「Tools」.「Options...」,弹出『Android SDK Manag ...

  6. java编程的78条黄金法则

    创建和销毁对象 1.考虑用静态工厂方法(返回类的实例的静态方法)代替构造器2.遇到多个构造器参数时要考虑用构造器3.用私有构造器或者枚举类型强化Singleton属性4.通过私有构造器强化不可实例化的 ...

  7. java 求第n小的质数

    package a小米; import java.util.Scanner; public class prime { public static boolean isPrime(int n){ fo ...

  8. u-boot board_uart_init流程

    /** ****************************************************************************** * @author    Maox ...

  9. Memento

    #include <iostream> #include <string> using namespace std; class Memento { public: Memen ...

  10. Linux搭建NFS提供磁盘给Windows使用

    在Windows2008系统下设置挂载Linux服务器磁盘 一.系统环境 系统平台:CentOS release 5.8 (Final) NFS Server IP:X....X...153.157 ...