webpack - loader

2020-01-12  本文已影响0人  我叫Aliya但是被占用了

Webpack学习笔记
webpack - 项目优化
webpack实现原理
webpack - loader
webpack - plugin
webpack - 项目优化2

    resolveLoader: {
        // loader查找规则
        modules: [path.resolve(__dirname, 'node_modules'),path.resolve(__dirname, 'loaders')],
        // loader别名
        alias: {
            txt: path.resolve(__dirname, 'loaders', 'txt.js')
        }
    },
    module: {
        rules: [
            {
                exclude: /node_modules/,
                test: /\.txt$/,
                use: [ path.resolve(__dirname, 'loaders', 'txt.js') ] 
            },
            {
                exclude: /node_modules/,
                test: /\.txt$/,
                use: 'txt'
            },
            {
                test: /\.less$/,
                use: [ 'style.js', 'less.js' ]
            }
            {
                test: /\.less$/,
                use: [ 'style.js', 'less.js' ],
                enforce: 'pre'  // pre loader
            }
loader.pitch = function () { console.log('我会最早执行,即洋葱的前半部分'); return 'xxx' }
require('!inline-loader!./a.js')     // 不再匹配其它loader
require('-inline-loader!./a.js')     // 把pre和normal屏蔽掉
require('inline-loader!./a.js')      // 没有normal

options

            {
                exclude: /node_modules/,
                test: /\.txt$/,
                use: {
                    loader: 'txt',
                    options: { content: '明治维新燃油费' }  // 为loader配置options
                }
            },
let loaderUtils = require('loader-utils')
module.exports = function (source) {
    // this上下文相关属性和方法参见 https://www.webpackjs.com/api/loaders/
    // 读取webpack.config.js中配置的options
    // console.log(this.query) 
    // let content = this.query && this.query.content || '统一换成这个'
    
    // 好鸡肋,为什么要用
    // console.log(loaderUtils.getOptions(this))
    let query = loaderUtils.getOptions(this)
    let content = query && query.content || '统一换成这个'

    // return `module.exports = "${content}"`

    let cb = this.async()   // 将Loader变为异步loader
    setTimeout(() => cb(`module.exports = "${content}"`), 2000)
}

打包后

"./common/xx.txt": eval("module.exports = \"明治维新燃油费\"\n\n//# sourceURL=webpack:///./common/xx.txt?");

参数校验

    module: {
        rules: [
            {
                test: /\.html/,
                use: {
                    loader: 'html-minify-loader.js',
                    options: {
                        comments: false
                    }
                }
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: './template/index.html'
        })
        // 本质上是require了index.html,所以loader会起作用
        // 可以配置嵌入的js是否有?hash、是否去掉”、是否消除空白等
    ]
// html-minify-loader.js
let Minimize = require('minimize')  // 代码压缩
let schemaUtils = require('schema-utils') // 参数校验
function loader (source) {
    let porps = {
        "type": "object",
        "properties": {
          "comments": {
            "type": "boolean"
          }
        }
    } 
    // 验证不通过会抛出异常
    schemaUtils(porps, this.query, 'html-minify-loader')

    let mini = new Minimize(this.query)
    source = mini.parse(source); 
    return `module.exports = ${JSON.stringify(source)}`
}
module.exports = loader

根据模板生成入口html文件

    module: {
        rules: [
            {
                test: /\.html/,
                use: {
                    loader: 'html-layout-loader.js',
                    options: {
                        template: path.resolve(__dirname, 'template', 'index.html'),
                        reg: /\{\{content\}\}/
                    }
                }
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'home.html',
            template: './template/home.html'
        }),
        new HtmlWebpackPlugin({
            filename: 'login.html',
            template: './template/login.html'
        })
    ]
// html-layout-loader.js
let fs = require('fs')
// 根据模板生成入口html文件
function loader (source) {
    let {template, reg} = this.query
    let cb = this.async()
    fs.readFile(template, 'utf8', function (err, data) {
        source = data.replace(reg, source)
        cb(err, `module.exports = ${JSON.stringify(source)}`)
    })
    // return `module.exports = ${JSON.stringify(source)}`
}
module.exports = loader

npx webpack --watch 对模板进行watch

// html-layout-loader.js
    ...
    // webpack --watch 时,对模板也进行实时打包
    this.addDependency(template)    
    ...

处理图片资源

        rules: [
            {
                test: /\.png$/,
                use: {
                    loader: 'file-loader.js', // 处理引用的图片路径
                }
            }
        ]
// file-loader.js
let loaderUtils = require('loader-utils')
function loader (source) {
    // 生成新文件名,8位哈希值.原名.原扩展名
    let name = loaderUtils.interpolateName(this, `[hash:8].[name].[ext]`, { content: '哈希摘要的依据' })

    // 发射到目标文件根目录
    this.emitFile(name, source)

    return `module.exports = "${name}"`
}
loader.raw = true;  // 表示source是二进制(buffer)
module.exports = loader

打包后dist目标下出现f371901e.avatar.png,bundle中"./common/avatar.png":(function(module, exports) { eval("module.exports = \"f371901e.avatar.png\"...

        rules: [
            {
                test: /\.png$/,
                use: {
                    loader: 'url-loader.js',     // base64化小图
                    options: { minisize: 50 * 1024 }
                }
            }
        ]
// url-loader.js
const mime = require("mime");
function loader (source) {
    let { minisize } = this.query
    if (source.length > minisize) {
        return require('./file-loader').call(this, source)
    } else { 
        // 小于指定大小,base64化图片
        let type = mime.getType(this.resourcePath)
        return `module.exports = "data:${type};base64,${source.toString('base64')}"`
    } 
}
loader.raw = true;  // 表示source是二进制(buffer)
module.exports = loader

打包后dist/bundle.js中"./common/avatar.png":(function(module, exports) { eval("module.exports = \"data:image/png;base64,iVBORw...

上一篇 下一篇

猜你喜欢

热点阅读