案例实战之如何写一个webpack loader

通过以下几个实例掌握webpack loader的写法

1.写一个多语言替换的loader

在index.js在页面上插入了一个{{title}}文本,我们需要在打包的时候将其替换成对应的多语言

function component() {
    let element = document.createElement('div')
    let str = 'hello webpack loader <h1>{{title}}</h1>'
    element.innerHTML = str
    element.classList.add('hello')
    document.body.appendChild(element)
}
component()

loader的写法

const loaderUtils = require('loader-utils')
const langEnv = process.env.langEnv || 'English'
const languageLoader = function (source) {
    let options = loaderUtils.getOptions(this)    //获取配置传递过来的参数
    let sources
    if (langEnv.trim() == 'English') {
        sources = source.replace('{{title}}', 'English title')
    } else {
        sources = source.replace('{{title}}', '中文标题')
    }
    return sources
}
module.exports = languageLoader

使用自己定义的loader

// 配置loader的别名
resolveLoader: {
    modules: ['node_modules', './loaders'],
    alias: {
         "language-loader": utils.resolve('./loaders/languageLoader.js'),
    }
},
module:{
    rules:[
        {
            test:/\.js?$/,
            use: [
                { loader: 'babel-loader' },
                {
                    loader: 'language-loader',
                    options: {
                        name: '多语言转换的loader'
                    }
                }
            ]
        }
    ]
}

设置环境变量

"dev": "set langEnv=English && webpack --config ./webpack.dev.config.js",

执行npm run dev

2.写一个转换less的loader

const less = require('less')
function loader(source) {
    let css = ''
    less.render(source, (err, c) => {
        if (err) {
            console.log(err)
            return
        }
        css = c.css
    })
    return css
}
module.exports = loader

3.写一个style-loader

const loaderUtils = require('loader-utils')
function loader(source) {
    console.log('style-loader', this.resourcePath, source)
    let sourcec = source
    let style = `
        let style = document.createElement('style');
        style.innerHTML = ${JSON.stringify(sourcec)}
        document.head.appendChild(style)`
    return style
}

4.写一个file-loader

// 这是一个文件打包loader
const loaderUtils = require('loader-utils')
function loader(source) {
    let filename = loaderUtils.interpolateName(this, '[hash].[ext]', {
        content: source
    })
    this.emitFile(filename, source)
    return `module.exports="${filename}"` 
}
loader.raw = true   //转换为二进制
module.exports = loader

5.写一个url-loader

// url-loader
const loaderUtils = require('loader-utils')
const mime = require('mime')
function loader(source) {
    let { limit } = loaderUtils.getOptions(this)
    console.log(this.resoucePath)   //获取资源的路径
    let fileType = mime.getType(this.resoucePath)
    if (limit && limit > source.length) {
        return `module.exports="data:${fileType};base64,${source.toString('base64')}"`
    } else {
        return require('./file-loader.js').call(this, source)
    }
}
loader.raw = true
module.exports = loader

6.写一个打包不同皮肤的css loader

我需要在打包的时候传入一个配置参数,就可以调取到不同的less颜色变量,从而渲染成不同风格的css文件

const loaderUtils = require('loader-utils');
const STYLE_TAG_REG = /(\<style.*?lang="less?".*?\>)([\S\s]*?)(\<\/style\>)/g;
//多站点皮肤切换
let themeName = process.argv[2] || 'blackTheme';
let injectUrl = "@import '/assets/theme/"+themeName+"/diffColor.less';";
let injectedTemplate = injectUrl;
module.exports = function (source) {
    let options = loaderUtils.getOptions(this);
    if (options && options.injectInVueFile) {
        // 向每一个.vue文件的<style>块中注入
        return source.replace(STYLE_TAG_REG, `$1${injectedTemplate}$2$3`);
    }
    return injectedTemplate + source;
};

是不是写一个loader是一件很简单的事情呢,十几行代码就搞定了啦

相关推荐