本文首发于Array_Huang的技术博客——
实用至上
,非经作者同意,请勿转载。
原文地址:https://segmentfault.com/a/1190000006897458
如果您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang
过去讲前端模块化、组件化,更多还是停留在js层面,毕竟js作为一种更典型的程序语言,在这方面的想象和操作空间都更大一些。但近年来,组件化要求得更多了,HTML/CSS/JS这三件套一件可都不能少(甚至包括其它类型的资源,比如说图片),而这样的组件,无疑是高内聚
的。
本文将介绍如何使用webpack来打包less/css(没用过sass,但毕竟也是通过loader来加载的,相信与less无异),首先是介绍相关的webpack plugin&loader,然后将介绍如何加载不同应用层次的less/css。
在《webpack多页应用架构系列(二):webpack配置常用部分有哪些?》里我就说过,webpack的核心只能打包js文件,而js以外的资源都是靠loader进行转换或做出相应的处理的。下面我就来介绍打包less/css所需要的loader。
针对less文件,我们首先需要使用less-loader来加载。less-loader会调用所依赖的less
模块对less文件进行编译(包括@import
语法)。至于说less-loader所接受的参数,实质上大部分是传递给less
模块使用的参数,由于我本人应用less的程度不深,因此没有传任何参数、直接就使用了。如果你之前对less
模块就已经有了一套配置的话,请参考less-loader的文档进行配置。
另外,less-loader并不会针对url()
语法做特别的转换,因此,如果你想把url()
语句里涉及到的文件(比如图片、字体文件等)也一并用webpack打包的话,就必须利用管道交给css-loader做进一步的处理。
针对css文件,我们需要使用css-loader来加载.css-loader的功能比较强大,一些新颖的特性比如Local Scope
或是CSS Modules
都是支持的。
我目前只用到了css-loader的压缩功能(Minification),对于这个功能,有一点是需要注意的,那就是如果你的代码里也和我一样,有许多为了浏览器兼容性的废弃CSS代码的话,请务必关闭autoprefixer
已避免你的废弃CSS代码被css-loader删除了,形如css?minimize&-autoprefixer
。
上面提到css-loader会对url()
语句做处理,这里稍微再说两句。在less/css里的这url()
语句,在css-loader看来,就跟require()
语句是一样的,只要在webpack配置文件里定义好加载各类型资源的loader,那这url()
语句实际上什么资源都能处理。一般我在url()
语句都会以相对路径的方式(相对于此语句所在的less/css文件)来指定文件路径;请不要使用以/
开头(即相对于网站根目录,因为对于文件系统来说,这明显是令人混淆的)的路径,尽管css-loader也可以通过设置root
参数来适配。
习惯用postcss的童鞋们有福啦,webpack可以通过postcss-loader来兼容postcss。由于postcss只算是一个加分项,因此这里也不作过多介绍,只介绍一下如何把postcss撘进webpack,不明白的童鞋麻烦先把postcss搞懂了再看。
放上我的脚手架项目的代码:
var precss = require('precss');
var autoprefixer = require('autoprefixer');
module.exports = {
module: {
loaders: [
{
test: /\.css$/,
exclude: /node_modules|bootstrap/,
loader: 'css?minimize&-autoprefixer!postcss',
}
]
},
postcss: function () {
return [precss, autoprefixer({
remove: false,
browsers: ['ie >= 8', '> 1% in CN'],
})];
}
}
从loader的配置'css?minimize&-autoprefixer!postcss'
上看,实际上就是先让postcss-loader处理完了再传递给css-loader。而postcss
项则是postcss-loader所接受的参数,实际上就是返回一个包含你所需要的postcss's plugins的数组啦,这些plugin有各自的初始化参数,不过这些都是postcss的内容了,这里就不做介绍了。
加载less/css这一块主要用到的是extract-text-webpack-plugin
(下文简称为ExtractTextPlugin
吧),而且由于我用的是webpack 1
,因此用的也是相对应webpack 1
的版本(1的文档在这里不要搞错了哈)。
ExtractTextPlugin的作用是把各个trunk加载的css代码(可能是由less-loader转换过来的)合并成一个css文件并在页面加载的时候以<link>
的形式进行加载。
相对于使用style-loader直接把css代码段跟js打包在一起并在页面加载时以inline的形式插入DOM,我还是更喜欢ExtractTextPlugin生成并加载CSS文件的形式;倒不是看不惯inline的css,只是用文件形式来加载的话会快很多,尤其后面介绍用webpack来生成HTML的时候,这<link>
会直接生成在<head>
里,那么在CSS的加载上就跟传统的前端页面没有差别了,体验非常棒。
ExtractTextPlugin的初始化参数不多,唯一的必填项是filename
参数,也就是如何来命名生成的CSS文件。跟webpack配置里的output.filename参数类似,这ExtractTextPlugin的filename参数也允许使用变量,包括[id]、[name]和[contenthash];理论上来说如果只有一个trunk,那么不用这些变量,写死一个文件名也是可以的,但由于我们要做的是多页应用,必然存在多个trunk(至少每个entry都对应一个trunk啦)。这里我是这么设置的:
new ExtractTextPlugin('[name]/styles.css'), [name]对应的是trunk的name,我在webpack配置中是这样
[name]
对应的是trunk的name,我在webpack配置中把各个entry的name都按index/index
、index/login
这样的形式来设置了,那么最后css的路径就会像这样:build/index/index/styles.css
,也就是跟trunk的js文件放一块了(js文件的路径形如build/index/index/entry.js
)。
除了要把这初始化后的ExtractTextPlugin放到webpack配置中的plugins
参数里,我们还要在loader配置里做相应的修改:
module.exports = {
module: {
loaders: [
{
test: /\.css$/,
exclude: /node_modules|bootstrap/,
loader: ExtractTextPlugin.extract('css?minimize&-autoprefixer!postcss'),
}
]
},
}
如此一来,ExtractTextPlugin就算是配置好了。
在我的设计中,有三种应用层次的less/css代码段:
基础的、公用的代码段,包括CSS框架、在CSS框架上进行定制的CSS theme,基本上每个页面都会应用到这些CSS代码段。
组件的代码段,这里的组件
既包括第三方的组件(比如说datepicker又或是paginator),也包括你自己写的组件(比如说顶部菜单栏、侧边菜单栏)。
每个页面独有的CSS代码段,很可能只是对某些细节进行微调。
本文首发于Array_Huang的技术博客——
实用至上
,非经作者同意,请勿转载。
原文地址:https://segmentfault.com/a/1190000006897458
如果您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang