webpack scss打包
webpack将css打包成一个bundle文件,对于打包遇到的一些问题做一些总结。
前言
因为基于sass打包,所以先讲解一下sass基础知识。
!default 默认值
Notes: 变量可以覆盖,但是无法变量提升
$content: "First content";
$content: "Second content?" !default;
$new_content: "First time reference" !default;
#main {
content: $content;
new-content: $new_content;
}
$content: "Hoisting content";
#submain {
content: $content;
new-content: $new_content;
}
this Compiled Result:
#main {
content: "First content";
new-content: "First time reference";
}
#submain {
content: "Hoisting content";
new-content: "First time reference";
}
@import 导入
Sass 拓展了 @import 的功能,允许其导入 SCSS 或 Sass 文件。被导入的文件将合并编译( 先合并再编译)到同一个 CSS 文件中,另外,被导入的文件中所包含的变量或者混合指令 (mixin) 都可以在导入的文件中使用。
片段(Partials)需要导入 SCSS 或者 Sass 文件,但又不希望将其编译为 CSS,只需要在文件名前添加下划线,将文件命名为 _colors.scss,便不会编译 _colors.css 文件。
@import "colors";
Notes:webpack打包js文件可以extensions补全后缀.js,但是因为scss的Partials所以无法使用补全。
require/import
webpack在ES6模块加载打包时是先编译再合并
webpack配置
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
// bundle
const extractSass = new ExtractTextPlugin({
filename: '[name].css',
allChunks: false
})
const config = {
entry: {
index: ['babel-polyfill', './screen/demo/index.jsx']
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js',
libraryTarget: 'umd',
},
module: {
{
test: /\.(scss|sass)$/,
use: extractSass.extract({
use: [{
loader: "css-loader"
}, {
loader: "sass-loader"
}],
// use style-loader in development
fallback: "style-loader"
})
}],
},
resolve: {
extensions: ['*', '.js', '.jsx'], // 后缀名自动补全
mainFiles: ['index'], // 默认js文件名
},
plugins: [
extractSass
]
};
module.exports = [config];
使用
一、@import
1、简单
variable.scss
$white: #fff;
a.scss
@import 'variable.scss';
html{
background-color: $white;
}
b.scss
@import 'variable.scss';
body{
background-color: $white;
}
this Compiled Result:
/*a.scss*/
html{
background-color: #fff;
}
/*b.scss*/
body{
background-color: #fff;
}
2、嵌套
variable.scss
$white: #fff;
a.scss
/*@import 'variable.scss';*/
html{
background-color: $white;
}
b.scss
@import 'variable.scss';
@import 'b.scss';
body{
background-color: $white;
}
this Compiled Result:
/*b.scss*/
html{
background-color: #fff;
}
body{
background-color: #fff;
}
3、复杂嵌套
variable.scss
$white: #fff;
component.scss
@import 'variable.scss';
.component{
background-color: $white;
}
a.scss
/*@import 'variable.scss';*/
@import 'component.scss';
html{
background-color: $white;
}
b.scss
@import 'variable.scss';
@import 'a.scss';
@import 'component.scss';
body{
background-color: $white;
}
this Compiled Result:
/*b.scss*/
.component{
background-color: #fff;
}
html{
background-color: #fff;
}
/* this is duplicated */
.component{
background-color: #fff;
}
body{
background-color: #fff;
}
仔细看发现编译后的结果component.scss被重复编译,因为@import是合并文件,但是variable和mixin是不会被编译输出的,嵌套使用@import注意不要重复class,推荐写法:
新增index.scss
@import 'variable.scss';
@import 'a.scss';
@import 'b.scss';
@import 'component.scss';
a.scss
@import 'variable.scss';
/*@import 'component.scss';*/
html{
background-color: $white;
}
b.scss
@import 'variable.scss';
/*@import 'a.scss';
@import 'component.scss';*/
body{
background-color: $white;
}
最好就是统一入口引用,按需求嵌套,防止重复。但是顶层scss文件引入变量文件就可以使用的,为什么要每个文件都引用@import 'variable.scss';?后面会讲解。
4、node_modules模块
@import "~bootstrap/dist/css/bootstrap";
使用~声明不是相对地址,而是来自node_modules下的模块
二、require/import
variable.scss
$white: #fff;
a.scss
@import 'variable.scss';
html{
background-color: $white;
}
b.scss
/*@import 'variable.scss';*/
body{
background-color: $white;
}
a.jsx
import React, { Component } from 'react';
import './a.scss';
const TestA = (props, context)=>{
return (
<div className="test-child-background">test123456</div>
);
}
export default TestA;
b.jsx
import React, { Component } from 'react';
// quote variable.scss
import TestA from './a.jsx';
// not quote variable.scss
import './b.scss';
const TestB = (props)=>{
return (
<div className="test-background">
<TestA />
</div>
);
}
export default TestB;
//b.scss error
Undefined variable: "$white"
@import**是全局变量通用,先合并在编译,**而es6 Module语法import是按照单个文件加载的,webpack会先编译在合并,但是不会影响单个import的scss文件中的@import语法。a.scss和b.scss是分开编译在合并成一个文件,所以每个_单独的scss_文件最好引用全局变量文件。
优点:
- 引用全局变量文件,利于组件重用,不受引用文件作用域影响;
缺点:
- 如果是纯样式scss文件,
@import将会重复引用class,需要自己注意,issues有讨论,但是没有优美的解决方案。(less有@import (reference) 'base.less';语法来支持重复引用)