webpack 相关 loader、插件详解,带你完成一个进阶 demo

一、CSS 相关配置

1. 模块(必须配置):CSS打包 —> style-loader、 css-loader
  • 场景: 将CSS文件,通过 import 引入到JS中,webapck 运行会报错,为解决问题需安装并配置 css 方面的loader

  • 目的: 将CSS代码,打包到JS中,减少文件个数 减少HTTP请求

  • style-loader: 处理css文件中的 url() 等,npm 中网址

  • css-loader: 将css插入到页面的 <style> 中,npm 中网址

  • 重点注意: 配置时 style-loader 必须在 css-loader 前面

  • 安装: npm install style-loader css-loader --save-dev

  • 配置(写法一): 直接用use

// webpack.config.js 文件中配置如下

module: {
    rules: [
        {
            test:/\.css$/,
            use: ['style-loader','css-loader'] 
        }
    ]
}
  • 配置(写法二): 把use换成loader
// webpack.config.js 文件中配置如下

module: {
    rules: [
        {
            test:/\.css$/,
            loader: ['style-loader','css-loader'] 
        }
    ]
}
  • 配置(写法三): 用 use + loader 的写法 【常用】
// webpack.config.js 文件中配置如下

module: {
    rules: [
        {
            test:/\.css$/,
            use:[
                {
                    loader: 'style-loader'
                },
                {
                    loader: 'css-loader',
                    options: {
                        modules: true
                    }
                }
            ] 
        }
    ]
}
  • 打包: npm run build
2. 插件:CCC 分离 —> extract-text-webpack-plugin
  • 场景: 某些团队要求,将 CSS代码 单独提取,但 webpack 官方并不建议这样做(webpack 认为CSS就应该打包到JavasScript当中以减少http的请求数);为应对团队需求,我们可使用 CSS分离插件 extract-text-webpack-plugin

  • 依赖于:

    • style-loader 和 css-loader 这两个loader
  • 安装: npm install extract-text-webpack-plugin style-loader css-loader --save-dev

  • 配置:

// webpack.config.js 文件中配置如下:CSS 打包 并 分离

const extractTextPlugin = require("extract-text-webpack-plugin");

plugins: [
    new extractTextPlugin("/css/index.css")         // /css/index.css 是CSS分离后的路径,以 dist文件夹为根目录
]

module:{
    rules: [{
      test: /\.css$/,
      use: extractTextPlugin.extract({
        fallback: "style-loader",
        use: "css-loader"
      })
    }]
}
  • 打包: npm run build ;项目打包后,dist文件夹中就会出现 css文件夹(含分离出来的css文件)

  • 隐藏的问题:图片路径有问题: extract-text-webpack-plugin 插件很容易将 CSS分离出来,但是路径并不正确

  • 配置 publicPath 来解决路径问题: 相对路径 变为 绝对路径(正确的),这样速度也会更快

// webpack.config.js 文件中配置如下

var website ={
    publicPath:"http://localhost:3000/"
}


output:{
    path:path.resolve(__dirname,'dist'),
    filename:'[name].js',
    publicPath:website.publicPath   // 配置公共路径
},
3. 模块、插件:CSS 添加CSS3属性前缀 —> postcss-loader 、autoprefixer
  • 场景: 为了浏览器的兼容性,有时候我们必须加入 -webkit, -ms, -o, -moz 这些前缀,为了让CSS3的样式生效

  • postcss 的相关配置项文档

  • postcss-loader: (模块)添加 CSS3前缀

  • autoprefixer: (插件)添加 CSS3前缀

  • 依赖于:

    • style-loader 和 css-loader 这两个loader
  • 安装: npm install postcss-loader autoprefixer style-loader css-loader --save-dev

  • 基础配置:

    • postCSS推荐在项目根目录(和 webpack.config.js 同级),建立一个 postcss.config.js 文件
// postcss.config.js 文件中配置如下

module.exports = {
    plugins: [
        require('autoprefixer')
    ]
}
  • 配置: 添加CSS3前缀后,不分离CSS
// webpack.config.js 文件中配置如下

module: {
    rules: [{
          test: /\.css$/,
          use: [
                {
                  loader: "style-loader"
                }, {
                  loader: "css-loader",
                  options: {
                     modules: true
                  }
                }, {
                  loader: "postcss-loader"
                }
          ]
    }]
}
  • 配置(可选): 添加CSS3前缀后,分离CSS
    • 安装:npm install extract-text-webpack-plugin --save-dev
// webpack.config.js 文件中配置如下

const extractTextPlugin = require("extract-text-webpack-plugin");

plugins: [
    new extractTextPlugin('/css/index.css'), // 分离CSS
]

module: {
    rules: [{
        test: /\.css$/,
        use: extractTextPlugin.extract({
            fallback: 'style-loader',
            use: [{
                    loader: 'css-loader',
                    options: {
                        importLoaders: 1
                    }
                },
                'postcss-loader'
            ]
        })
    }]
}
4. 模块配置: LESS 的打包 和 分离 — less-loader
  • less-loader: 打包less 文件 (编译)

  • 依赖于:

    • less 模块:使用Less,我们要首先安装Less的服务

    • style-loader 和 css-loader 这两个loader

  • 安装: npm install less less-loader style-loader css-loader --save-dev

  • 配置: (选项一)less打包后 不分离

// webpack.config.js 文件中配置如下

module: {
    rules: [{
        test: /\.less$/,
        use: [
            {
                loader: 'style-loader'
            },
            {
                loader: 'css-loader'
            },
            {
                loader: 'less-loader'
            }
        ]
    }]
}
  • 配置: (选项二)less打包后 分离less(css)
    • 安装:npm install extract-text-webpack-plugin --save-dev
// webpack.config.js 文件中配置如下

const extractTextPlugin = require("extract-text-webpack-plugin");

plugins: [
    new extractTextPlugin('/css/index.css'), // 分离CSS
]

module: {
    rules: [{
        test: /\.less$/,
        use: extractTextPlugin.extract({
            use: [{
                loader: "css-loader"
            }, {
                loader: "less-loader"
            }],
            // use style-loader in development
            fallback: "style-loader"
        })
    }]
}
5. 模块配置: SCSS 的打包 和 分离 —> sass-loader
  • sass-loader: 打包scss 文件 (编译)

  • 依赖于:

    • node-sass 模块

    • style-loader 和 css-loader 这两个loader

  • 安装: npm install node-sass sass-loader style-loader css-loader --save-dev

  • 配置: (选项一)sass打包后 不分离

// webpack.config.js 文件中配置如下

module: {
    rules: [{
        test: /\.scss$/,
        use: [
            {
                loader: 'style-loader'
            },
            {
                loader: 'css-loader'
            },
            {
                loader: 'sass-loader'
            }
        ]
    }]
}
  • 配置: (选项二)scss打包后 分离scss(css)
    • 安装:npm install extract-text-webpack-plugin --save-dev
// webpack.config.js 文件中配置如下

const extractTextPlugin = require("extract-text-webpack-plugin");

plugins: [
    new extractTextPlugin('/css/index.css'), // 分离CSS
]

module: {
    rules: [{
        test: /\.scss$/,
        use: extractTextPlugin.extract({
            use: [{
                loader: "css-loader"
            }, {
                loader: "sass-loader"
            }],
            // use style-loader in development
            fallback: "style-loader"
        })
    }]
}
6. 插件配置: 净化 CSS代码 —> PurifyCSS-webpack 、 purify-css
  • 场景: 随着项目的更新迭代,会出现一些冗余的CSS代码,并没有使用,这是需要净化CSS,去掉无用的CSS代码,减少代码体积

  • 约束: 目前看来,净化CSS的插件,必须配合 插件 extract-text-webpack-plugin 使用

  • 插件 Purifycss-webpack: 净化CSS的插件(清除没有使用的CSS)

  • 依赖于:

    • purify-css: PurifyCSS-webpack 依赖于 purify-css

    • node全局对象 glob: 因为 需要同步检查 全局html模板

const glob = require('glob');       // webpack.config.js 文件中 引入node全局对象

const PurifycssPlugin = require("purifycss-webpack");   // 引入插件
  • 安装: npm install purifycss-webpack purify-css --save-dev

  • 配置:

// webpack.config.js 文件中 配置如下


plugins: [
    new PurifycssPlugin({                      // 净化 CSS
        paths: glob.sync(path.join(__dirname, 'src/*.html')),
    })
]

二、 图片 配置

1. 模块(必须配置):HTML / CSS 中 图片转码、打包后的路径转化 —> url-loader 、file-loader
  • 场景: CSS文件中,给标签引入背景图片,webpack打包,终端报错

  • file-loader: 解决路径引用问题【不限于解决CSS中的路径】 我们都知道,webpack最终会将多个文件,打包成一个文件,源码中的路径是相对路径,打包后需要根据打包结果调整资源路径,file-name 就是解决这个问题的

  • url-loader: 优化图片形式(优化性能)、解决路径问题。url-loader提供了一个limit参数,小于这个大小的图片,会被编码成 dataURl(Base64格式),相当于把图片数据翻译成一串字符,这样便可以减少HTTP资源请求,优化性能;大于limit参数的图片,会使用 file-loader 进行 copy(路径转换)

  • 安装: npm install file-loader url-loader --save-dev

  • 配置url-loader:

// webpack.config.js 文件中配置如下

module: {
    rules: [{
        test:/\.(png|jpg|gif)/ ,
        use:[{
            loader:'url-loader',
            options:{
                limit:500000,           // 小于500000B 的图片打成Base64的格式,写入JS
                outputPath: '/images/'  // 大于500000B 的图片输出路径(将图片统一输出到一个文件夹中)
            }
        }]
     }
   ]
}
  • 打包: npm run build

  • 疑问:为什么只使用了 url-loader ?

    • 关系:url-loader 中封装(内置)了 file-loader

    • 实际上,我们可以看出,url-loader 有两种作用

      • 文件大小小于limit参数: 图片转码, url-loader将会把文件转为DataURL(Base64格式)

      • 文件大小大于limit参数: 打包后的路径转化, url-loader会调用file-loader进行处理,参数也会直接传给file-loader

    • 其实我们只安装一个url-loader就可以了。但是为了以后的操作方便,我们这里就顺便安装上 file-loader

2. 模块(必须配置):HTML 中 <img> 的处理 —> html-withimg-loader
  • 场景: webpack 不建议使用 标签 <img> 来引入图片,它建议所有图片都使用背景图方式;若在html中使用 <img>,打包后 <img> 标签的路径 及 引入的图片,不会被处理,使用 html-withimg-loader 这个 loader 可解决 html中引入 <img> 的问题(国人开发的 loader)

  • 安装: npm install html-withimg-loader --save-dev

  • 配置:

// webpack.config.js 文件中配置如下

module: {
    rules: [{
        test: /\.(htm|html)$/i,
         use:[{
            loader: 'html-withimg-loader'
         }] 
    }]
}
  • 打包: npm run build

三、JS 相关配置

1. 插件配置:JS压缩 —> uglifyjs-webpack-plugin
  • webpack 内部集成插件 uglifyjs-webpack-plugin,无需安装

  • 配置:

// webpack.config.js 文件中配置如下


const uglify = require('uglifyjs-webpack-plugin');

plugins: [
    new uglify()
]
2. 模块配置:babel 转化
  • 场景: 前端开发中,ES6、ES7语法已盛行,但一些浏览器对 ES6 、ES7 语法不完全支持,为兼容所有浏览器,JS代码在部署时需要将 ES6、ES7 转为 浏览器支持的语法

  • Babel是什么? 一个 JavaScript 语法的编译器,可做到但不限于如下:

    • ECMAScript 语法转换

    • 使用基于JavaScript进行了扩展的语言,比如React的JSX,转为 JS语法

    • 编译不同的 JS,需要安装不同的 npm依赖包 详细见官网 / bebel中文网

  • 模块:babel-loader

  • 依赖于:

    • babel-core: babel的核心模块,需要单独安装

    • 以下 选一个安装即可:

      • babel-preset-env:

        • 配置名: env
        • 可选【官方推荐】
        • babel将 ES6、ES7 转为 浏览器支持的JS语法
      • babel-preset-es2015:

        • 配置名: es2015
        • 可选【官方 不再推荐】
        • babel将 ES6、ES7 转为 浏览器支持的JS语法
      • babel-preset-react:

        • 配置名: react
        • 可选
        • babel 将JSX语法 转为 浏览器支持的JS语法
  • 需求: 将 ES6、ES7 转为兼容代码

  • 安装: npm install babel-loader babel-core babel-preset-env --save-dev

  • 配置:

// webpack.config.js 文件中配置如下

module: {
    rules: [{
        test: /\.js$/,
        use: [
            {
                loader: 'babel-loader',
                options: {
                    presets: ['env']
                }
            }
        ],
        exclude: /node_modules/         // 屏蔽掉的文件
    }]
}
  • 配置优化: (可选)

    • 项目一般都使用这种方式,配置 babel

    • 考虑到 babel 有很多配置项,优化:在项目的根目录下,新建 .babelrc 文件,将 babel 配置项 统一写在 .babelrc 文件中

    • .babelrc 配置参考

// webpack.config.js 文件中配置如下

module: {
    rules: [{
        test: /\.js$/,
        use: ['babel-loader'],
        exclude: /node_modules/
    }]
}
// .babelrc 文件中配置 如下:
// 还需要安装  babel-preset-stage-0 babel-plugin-transform-runtime babel-plugin-transform-remove-console

{
    "presets": [
        ["env", { "modules": false }],
        "stage-0"               // stage-0 其实包含了 stage-[1-3] ,表示 state-0 及以上阶段的语法都会被转换,设置 state-0 也是最全面的babel转换设置
    ],
    "plugins": [
        "transform-runtime",            // 来处理全局函数和优化babel编译
        "transform-remove-console"      // 编译后的代码都会移除console.*
    ],
    "comments": false                   // 注释不被打包进去
}

四、基础 demo 代码

demo 功能 说明
  • 实现功能:

    • HTML、JS 、CSS 、LESS 、SCSS 代码 的编写、打包

    • 图片的使用(HTML 中 img 标签的使用、CSS 中背景图的使用)

    • CSS 、LESS、SCSS 的前缀(不含:分离、净化,这个中能可配置)

    • JS 代码 的 打包、babel 转化(不含压缩 JS,这个功能了配置)

    • 本地服务热更新(启动本地服务后,修改代码,页面自动刷新)

  • 未实现功能:

    • 未实现:SCSS 代码 的 编写、打包
demo 结构 说明
  • src 文件夹 (新建):开发环境的代码

  • dist 文件夹 (不用自己建,打包后自动生成):生产环境的代码

  • node_modules 文件夹 (自动生成):存放 项目的依赖模块

  • webpack.config.js 文件 (新建):webpack 配置文件

  • package.json 文件npm init 后自动生成):项目描述文件

  • postcss.config.js 文件(新建):通过此文件 配置 postcss

  • .babelrc 文件 (新建):babel-loader 配置中的 option 选项,单独写在此文件中

相关代码
  • package.json 文件:
{
  "name": "webpack-middle",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack",
    "server": "webpack-dev-server"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^8.1.0",
    "css-loader": "^0.28.10",
    "file-loader": "^1.1.11",
    "html-webpack-plugin": "^2.30.1",
    "html-withimg-loader": "^0.1.16",
    "less": "^3.0.1",
    "less-loader": "^4.0.6",
    "node-sass": "^4.7.2",
    "postcss-loader": "^2.1.1",
    "sass-loader": "^6.0.7",
    "style-loader": "^0.20.2",
    "url-loader": "^1.0.1",
    "webpack": "^3.10.0",
    "webpack-dev-server": "^2.11.1",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.6.1",
    "babel-plugin-transform-remove-console": "^6.9.0",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-stage-0": "^6.24.1"
  },
  "dependencies": {

  }
}
  • webpack.config.js 文件:
const glob = require('glob');
const path = require('path');
const htmlPlugin = require('html-webpack-plugin');



module.exports = {
    entry: {
        index: './src/index.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    },
    module: {
        rules: [{
                test: /\.css$/,
                use: [{
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader'
                    },
                    {
                        loader: "postcss-loader"
                    }
                ]
            },
            {
                test: /\.less$/,
                use: [{
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader'
                    },
                    {
                        loader: 'less-loader'
                    }
                ]
            },
            {
                test: /\.scss$/,
                use: [{
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader'
                    },
                    {
                        loader: 'sass-loader'
                    }
                ]
            },
            {
                test: /\.(png|jpg|gif)/,
                use: [{
                    loader: 'url-loader',
                    options: {
                        limit: 500000,
                        outputPath: '/images/'
                    }
                }]
            },
            {
                test: /\.(htm|html)$/i,
                use: [{
                    loader: 'html-withimg-loader'
                }]
            },
            {
                test: /\.js$/,
                use: ['babel-loader'],
                exclude: /node_modules/
            }
        ]
    },
    plugins: [
        new htmlPlugin({
            minify: {
                removeAttributeQuotes: true
            },
            hash: true,
            template: './src/index.html'
        })

    ],
    devServer: {
        contentBase: path.resolve(__dirname, 'dist'), // 服务文件路径
        compress: true, // 启动服务压缩
        host: 'localhost',
        port: 2000
    }
}
  • postcss.config.js 文件:
// postcss 的相关配置
module.exports = {
    plugins: [      // 引入插件
        require('autoprefixer')
    ]
}
  • .babelrc 文件:
{
    "presets": [
        ["env", { "modules": false }],
        "stage-0"               // stage-0 其实包含了 stage-[1-3] ,表示 state-0 及以上阶段的语法都会被转换,设置 state-0 也是最全面的babel转换设置
    ],
    "plugins": [
        "transform-runtime",            // 来处理全局函数和优化babel编译
        "transform-remove-console"      // 编译后的代码都会移除console.*
    ],
    "comments": false                   // 注释不被打包进去
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值