接下来我们来解析 CSS SCSS LESS ES6 图片 ,为什么我们要解析这些东西,因为webpack只认js文件。
先在 src 下新建一个 index.css,并且在 index.js 中引入(import './index.css';)
解析CSS 需要两个 loader,分别是 css-loader style-loader
css-loader的作用是解析CSS语法,并且把解析后的结果传递给 style-loader
style-loader的作用是将传递的css变成style标签插入到html中,所以我们要先用 css-loader,再用 style-loader。
loader 的执行顺序
默认是从下到上执行,从右到左执行。
npm install css-loader style-loader --save-dev
我们在 webpack.base.js 中的 base 对象中新增一个对象,并在index.css中写入 background:red;
const base = {
...
module:{
// 转化什么文件 用什么去转 使用哪些loader
// loader 的写法有三种 [] {} ''
rules:[
{
test:/\.css$/, // 转换以css结尾的文件
use:['style-loader','css-loader']
}
]
},
...
}
再 npm run dev 执行下试试
我们再看 scss less 怎么转换。
sass 需要的包 node-sass sass-loader
less 需要的包 less less-loader
stylus 需要的包 stylus stylus-loader
我们先来看看 sass,先在src 下新建个 a.scss文件,并写入
$background:black;
div{
width:100px;
height:100px;
background:$background;
}
并在 index.js 中引入(import './a.scss'),接着安装sass需要的包,并配置loader,同样是在webpack.base.js中
...
rules:[
{
test:/\.css$/, // 转换以css结尾的文件
use:['style-loader','css-loader']
},
{
// 匹配到scss结尾的文件,使用sass-loader来调用node-sass处理sass文件
test:/\.scss$/, // 转换以scss结尾的文件
use:['style-loader','css-loader','sass-loader']
}
]
...
接着 npm run dev 运行下
...
rules:[
{
test:/\.css$/, // 转换以css结尾的文件
use:['style-loader',{
loader:'css-loader',
options:{
// 给loader传递参数
// 表示如果从 css中又引入了sass文件,需要先从此loader之后执行一下后面的这个loader
// 此处写几,就表示要先走后面的几个loader
importLoaders:1
}
},'sass-loader']
}
]
...
打包CSS时可能还会遇到这样一种问题,如果你写了一些CSS3的语法,还需要兼容一些低版本的浏览器,我们还需要自己加前缀,此时就需要用到postcss-loader
npm install postcss-loader --save-dev
这个loader需要一个插件去支持 autoprefixer
npm install autoprefixer --save-dev
先说下它的配置,在css加上前缀后再转给style-loader,它需要在最后一个loader前面。
...
rules:[
{
test:/\.css$/, // 转换以css结尾的文件
use:['style-loader','postcss-loader','css-loader']
},
{
// 匹配到scss结尾的文件,使用sass-loader来调用node-sass处理sass文件
test:/\.scss$/, // 转换以scss结尾的文件
use:['style-loader','css-loader','postcss-loader','sass-loader']
}
]
...
此处我在a.scss文件中给 div 加了一个 transform: rotate(45deg)
声明一下,postcss需要有它自己的一个配置文件,叫postcss.config.js,所以我们新建一下它。再新建一个.browserslistrc文件,告诉postcss,我要覆盖95%的浏览器。
npm install mini-css-extract-plugin --save-dev
// 先在 webapck.base.js 中引入
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 开发环境下尽量别抽离,因为慢,此处我们判断下环境
...
rules:[
{
test:/\.css$/, // 转换以css结尾的文件
use:[isDev ? 'style-loader' : MiniCssExtractPlugin ,'css-loader']
},
...
]
plugins:[
// 不是开发环境才用
!isDev && new MiniCssExtractPlugin({
// 抽离出来的CSS 文件名
filename:'css/main.css'
}),
...
].filter(Boolean)
// 此处传Boolean 是因为 MiniCssExtractPlugin 的判断,如果是开发环境会返回个false
// false 在数组里不是找死嘛,此处我们用这个技巧,Boolean 是个函数,它可以帮我们把每个值变成一个布尔类型
// 如果是 false 的话 filter 会过滤掉
...
npm install optimize-css-assets-webpack-plugin --save-dev
它有一个缺点,就是如果使用这个插件压缩了CSS,那JS它就不管了,你还要自己压缩
npm install terser-webpack-plugin --save-dev
此处我们在 webpack.prod.js 中进行配置
// 压缩CSS
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// 压缩JS
const TerserWebpackPlugin = require('terser-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
mode:'production',
optimization:{
// 优化项
minimizer:[
// 可以放压缩方案
new OptimizeCSSAssetsPlugin(),
new TerserWebpackPlugin()
]
},
plugins:[
// 从 base 中挪过来的,只在生产环境下才清空打包目录比较好
new CleanWebpackPlugin(),
]
}
自己运行 build 看看吧。接下来我们处理图片,先在src目录下放一张图片,并在index.js中引入
// 引入图片
import logo from './logo.png';
// 需求,获取当前打包logo图片后的路径,并把路径给到src
let img = document.createElement('img');
img.src = logo;
document.body.appendChild(img);
解析图片需要对应的loader,此处用到的是 file-loader
npm install file-loader --save-dev
安装完后该配置了,在 base 配置中增加
...
module: {
rules: [
{
test:/\.(jpg|png|gif|jpeg)$/,
use:'file-loader'
}
]
}
...
file-loader 默认功能是拷贝的作用,但我希望比较小的图片可以转为base64,好处是不用发送,就需要用到另一个loader了
npm install url-loader --save-dev
并将上面的loader替换掉
module: {
rules: [
{
test:/\.(jpg|png|gif|jpeg)$/,
use:{
loader:'url-loader',
// 优化 如果大于100k的图片会默认使用file-loader
options:{
limit:100*1024,
name:'image/[contentHash].[ext]' // 打包放到image目录下
}
}
}
]
}
...
{
test:/\.(woff|ttf|eot|svg)$/,
use:'file-loader' // 对图标的处理,直接拷贝过去就行了
}
...
开始配置JS的转换,多是用于将es6转为es5,用的是babel的插件
babel-loader 是 babel 和 webpack 的桥梁,它默认会调 @babel/core,@babel/core会调用 @babel/preset-env 将 es6 转为 es5
为什么要加@,这个东西叫作用域,就是说把所有叫babel的包都放到babel的作用域下,省的重名
npm install @babel/core @babel/preset-env babel-loader --save-dev
在 index.js 中写一个 es6 语法
// 实现将es6 转为 es5
const fn = () => { }
fn()
在 webpack.base.js 中配置
rules: [
{
test:/\.js$/,
use:'babel-loader'
},
]
并且新建一个babel的配置文件(.babelrc),默认转换时会掉这个文件
{
"presets":[
// 执行顺序是从下到上 配的是多个插件
"@babel/preset-env"
],
"plugins": [
// 执行顺序是从上到下 配的是单个插件
]
}
再运行下,看下打包出来的有没有转换
npm install @babel/plugin-proposal-class-properties --save-dev
再改一下babel的配置文件
{
"presets":[
// 执行顺序是从下到上 配的是多个插件(插件包)
"@babel/preset-env"
],
"plugins": [
// 执行顺序是从上到下 配的是单个插件
// "babel/plugin-proposal-class-properties"
// 如果要传参的话,需要把它写过一个数组中
["@babel/plugin-proposal-class-properties",{"loose":true}]
]
}
再打包试试
如果你要写装饰器的话,也需要单独安装插件,装完在babel配置中再配一下,自己装吧,反正我不用。
{
"presets":[
// 执行顺序是从下到上 配的是多个插件(插件包)
"@babel/preset-env"
],
"plugins": [
// 执行顺序是从上到下 配的是单个插件
// "babel/plugin-proposal-class-properties"
// 如果要传参的话,需要把它写过一个数组中
["@babel/plugin-proposal-decorators",{"legacy":true}],
["@babel/plugin-proposal-class-properties",{"loose":true}]
]
}
[1,2,3].includes(2)。像这种实例上的语法它也不会转换,包括promise它也不会,就是不会转换API。 改一下 .bablerc
{
"presets":[
// 使用的API会自动转换,并且会按需加载
["@babel/preset-env",{
"useBuiltIns":"usage",
"corejs":2 // npm install core-js@2 --save-dev 也可以用3
}]
],
"plugins": [
// 解析装饰器
["@babel/plugin-proposal-decorators",{"legacy":true}],
// 解析类
["@babel/plugin-proposal-class-properties",{"loose":true}]
]
}
如果你的index.js中有一个A类,同时又引入了另一个JS,那个JS中同样也有一个A类,怎么办?需要用到 @babel/plugin-transform-runtime 这个插件,这个插件依赖于 @babel/runtime 插件,但它是自动帮我们调的,所以我们只需要安装 @babel/plugin-transform-runtime 就行了。
npm install @babel/plugin-transform-runtime --save-dev
再配置一下
{
"presets":[
// 使用的API会自动转换,并且会按需加载
["@babel/preset-env",{
"useBuiltIns":"usage",
"corejs":2 // npm install core-js@2 --save-dev 也可以用3
}]
],
"plugins": [
// 解析装饰器
["@babel/plugin-proposal-decorators",{"legacy":true}],
// 解析类
["@babel/plugin-proposal-class-properties",{"loose":true}],
"@babel/plugin-transform-runtime"
]
}
基本用法就到这里吧,下一章写怎么和VUE接合到一起,因为我们项目就是用的VUE。