webpack2--5模块加载器&extractTextPlugin

本文详细介绍Webpack如何处理CSS模块,包括使用loader处理各种样式文件,通过extract-text-webpack-plugin插件将CSS抽离,实现资源优化及图片压缩,确保代码高效运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

webpack将所有静态资源都认为是模块,比如javascript,css,less,typescript,jsx,图片等等。webpack引入了加载器的loader,对除javascript之外的资源处理成模块。
webpack的加载器之间可以进行串联,一个加载器的输出可以成为另一个加载器的输入。

Webpack将所有静态资源都认为是模块,而通过loader,几乎可以处理所有的静态资源,图片、css、sass之类的。并且通过一些插件如extract-text-webpack-plugin,可以将共用的css抽离出来

常用loader

安装css/sass/less loader加载器

cnpm install file-loader css-loader style-loader sass-loader ejs-loader html-loader jsx-loader image-webpack-loader --save-dev

webpack.config.js配置

module: {
    loaders: [
        {
            test: /\.((woff2?|svg)(\?v=[0-9]\.[0-9]\.[0-9]))|(woff2?|svg|jpe?g|png|gif|ico)$/,
            loaders: [
                // 小于10KB的图片会自动转成dataUrl
                'url?limit=10240&name=img/[hash:8].[name].[ext]',
                'image?{bypassOnDebug:true, progressive:true,optimizationLevel:3,pngquant:{quality:"65-80",speed:4}}'
            ]
        },
        {
            test: /\.((ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9]))|(ttf|eot)$/,
            loader: 'url?limit=10000&name=fonts/[hash:8].[name].[ext]'
        },
        {test: /\.(tpl|ejs)$/, loader: 'ejs'},
        {test: /\.css$/, loader: 'style-loader!css-loader'},
        { test: /\.scss$/, loader: 'style!css!sass'}
    ]
},

index.html增加div

<div class="small-webpack"></div>
<div class="webpack"></div>

增加index.css

.webpack {
    background: url(../img/webpack.png) no-repeat center;
    height:500px;
}
.small-webpack {
    background: url(../img/small-webpack.png) no-repeat center;
    height:250px;
}

index.js引入css

require('../css/index.css');

执行webpack
生产的目录结构
在这里插入图片描述
其中没有css文件,css被写入index.js中,index.js部分截图
在这里插入图片描述

  1. 图片用url-loader加载器处理,如果小于10kb,图片则被转化成base64格式的dataUrl
  2. css文件打包进入了js文件,如果不想css打包进js文件,可以强制吧css从js文件中国独立出来。webpack.js.org

extract-text-webpack-plugin

此类插件可以将公用的css抽离出来,从bundle中提取出特定的text到一个文件中。这样就可以把css从js中独立抽离出来。
安装$ npm install extract-text-webpack-plugin --save-dev
使用css为列

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")
    ]
}

插件将从每一个用到require("*.css")的entry chunks文件中抽离出css到单独的output文件。
多入口文件的extract使用实列

let ExtractTextPlugin = require('extract-text-webpack-plugin');

// multiple extract instances多个提取实例 
let extractCSS = new ExtractTextPlugin('stylesheets/[name].css');
let extractLESS = new ExtractTextPlugin('stylesheets/[name].less');

module.exports = {
  ...
  module: {
    loaders: [
      {test: /\.scss$/i, loader: extractCSS.extract(['css','sass'])},
      {test: /\.less$/i, loader: extractLESS.extract(['css','less'])},
      ...
    ]
  },
  plugins: [
    extractCSS,
    extractLESS
  ]
};

extractTextPlugin的api

new ExtractTextPlugin([id:string], filename: string, [options] )

  1. id:此插件实列唯一的标识。(仅用于高级用途,默认情况下自动生成)
  2. filename:结果文件的文件名。可以包含【name】、【id】和【contenthash】
  3. options:allchunks | disable。allchunks也从所有其他块中提取(默认情况下,它只从初始块中提取),disable禁用插件

ExtractTextPlugin.extract([notExtractLoader], loader , [options])
根据已有的loader,创建一个提取器,loader的再封装
4. notExtractLoader:(可选)当css没有被抽离时,加载器不应该使用(例如:当allChunks:false时,在一个additional 的chunk中)
5. loader:数组,用来转换css资源的加载器
6. options:publicPath,重写该加载器的设置

改造项目

cnpm install extract-text-webpack-plugin --save-dev安装插件到项目
修改webpack.config.js

var webpack = require("webpack");
var path = require("path");
var srcDir = path.resolve(process.cwd(), 'src');
var nodeModPath = path.resolve(__dirname, './node_modules');
var pathMap = require('./src/pathmap.json');
var glob = require('glob')
var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var entries = function () {
    var jsDir = path.resolve(srcDir, 'js')
    var entryFiles = glob.sync(jsDir + '/*.{js,jsx}')
    var map = {};

    for (var i = 0; i < entryFiles.length; i++) {
        var filePath = entryFiles[i];
        var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'));
        map[filename] = filePath;
    }
    return map;
}

var html_plugins = function () {
    var entryHtml = glob.sync(srcDir + '/*.html')
    var r = []
    var entriesFiles = entries()
    for (var i = 0; i < entryHtml.length; i++) {
        var filePath = entryHtml[i];
        var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'));
        var conf = {
            template: 'html!' + filePath,
            filename: filename + '.html'
        }
        //如果和入口js文件同名
        if (filename in entriesFiles) {
            conf.inject = 'body'
            conf.chunks = ['vendor', filename]
        }
        //跨页面引用,如pageA,pageB 共同引用了common-a-b.js,那么可以在这单独处理
        //if(pageA|pageB.test(filename)) conf.chunks.splice(1,0,'common-a-b')
        r.push(new HtmlWebpackPlugin(conf))
    }
    return r
}
var plugins = [];
var extractCSS = new ExtractTextPlugin('css/[name].css?[contenthash]')
var cssLoader = extractCSS.extract(['css'])
var sassLoader = extractCSS.extract(['css', 'sass'])

plugins.push(extractCSS);

plugins.push(new CommonsChunkPlugin({
    name: 'vendor',
    minChunks: Infinity
}));

module.exports = {
    entry: Object.assign(entries(), {
        // 用到什么公共lib(例如jquery.js),就把它加进vendor去,目的是将公用库单独提取打包
        'vendor': ['jquery', 'avalon']
    }),
    output: {
        path: path.join(__dirname, "dist"),
        filename: "[name].js",
        chunkFilename: '[chunkhash:8].chunk.js',
        publicPath: "/"
    },
    module: {
        loaders: [
            {
                test: /\.((woff2?|svg)(\?v=[0-9]\.[0-9]\.[0-9]))|(woff2?|svg|jpe?g|png|gif|ico)$/,
                loaders: [
                    //小于10KB的图片会自动转成dataUrl,
                    'url?limit=10000&name=img/[hash:8].[name].[ext]',
                    'image?{bypassOnDebug:true, progressive:true,optimizationLevel:3,pngquant:{quality:"65-80",speed:4}}'
                ]
            },
            {
                test: /\.((ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9]))|(ttf|eot)$/,
                loader: 'url?limit=10000&name=fonts/[hash:8].[name].[ext]'
            },
            {test: /\.(tpl|ejs)$/, loader: 'ejs'},
            {test: /\.css$/, loader: cssLoader},
            {test: /\.scss$/, loader: sassLoader}
        ]
    },
    resolve: {
        extensions: ['', '.js', '.css', '.scss', '.tpl', '.png', '.jpg'],
        root: [srcDir, nodeModPath],
        alias: pathMap,
        publicPath: '/'
    },
    plugins: plugins.concat(html_plugins())
}
分析
  1. 用ExtractTextPlugin 来抽离css
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var extractCSS = new ExtractTextPlugin('css/[name].css?[contenthash]')
var cssLoader = extractCSS.extract(['css'])
var sassLoader = extractCSS.extract(['css', 'sass'])

plugins.push(extractCSS);
......
//conf - module - loaders
{test: /\.css$/, loader: cssLoader},
{test: /\.scss$/, loader: sassLoader}
  1. css中 img的路径会出现问题,通过设置publicPath 解决,采用绝对路径
output: {
      ......
      publicPath: "/"
  },
  1. 运行webpack生成如下目录结构

在这里插入图片描述
1、css单独抽离,打包成单独的css文件;2、html自动引用css文件;3、小于10k的图片,转成base64 格式的 dataUrl;4、webpack.png 会被压缩,减少文件大小

  1. 生成的 dist/index.html 自动引用了 index.css 和相关的js,由于设置了publicPath 所以相应的链接都采用了绝对路径
    在这里插入图片描述
  2. 生成的 dist/index.css 小图片被转成了data:image形式:
    在这里插入图片描述
    1、css单独打包到css目录
    2、html自动注入了link 标签
    3、small-webpack.png 小于10k,被打包进了index.css
    4、webpack.png 由原来的50+k 被压缩成 10- k

webpack-dev-server看一下结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值