你了解几种webpack中的loader的使用方式和特殊符号?

305 阅读2分钟

# 前言

Webpack本身只能处理JS类型的文件,想要处理其他类型的文件,如.css,.vue等文件就需要借助loader来进行转换,所以loader又可以理解成把一段代码转换为令一段代码的加载器。

loader本身就是一个函数:接收源码,经过处理后再返回源码;

loader的引入方式

webpack.config.js 文件

const path = require('path');

module.exports = {
    mode: "development",
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [{
            test: /\.js$/,
            use: 'loader1'
        }]
    }
}

这时我们运行打包命令npx webpack会报一个找不到loader1的错误。假设我们创建一个loaders的文件夹来存放我们的loader,并创建一个laoder1.js内容如下:

// source: 源码
function loader(source) {
    console.log('我是loader1');

    return source;
}

module.exports = loader

那现在loader有了,引入loader的方式有几种呢???

方式一:通过path.resolve的绝对路径

module: {
    rules: [{
        test: /\.js$/,
        use: path.resolve(__dirname, 'loaders', 'loader1')
    }]
}

方式二:通过resolveLoader.alias起个别名

resolveLoader: {
    alias: {
        loader1: path.resolve(__dirname, 'loaders', 'loader1')
    }
},
module: {
    rules: [{
        test: /\.js$/,
        use: 'loader1'
    }]
}

方式三:通过resolveLoader.modules规定查找模块顺序

 resolveLoader: {
    // 模块的查找顺序
    modules: ['node_modules', path.resolve(__dirname, './src/loaders')],
    // 别名
    // alias: {
    //     loader1: path.resolve(__dirname, './src/loaders', 'loader1')
    // }
},
module: {
    rules: [{
        test: /\.js$/,
        use: 'loader1'
    }]
}

# loader 的执行顺序

loader的执行顺序是从下到上,从右到左,怎么理解呢?我们具体看下:

webpack.config.js 文件

const path = require('path');

module.exports = {
    mode: "development",
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    resolveLoader: {
        // 模块的查找顺序
        modules: ['node_modules', path.resolve(__dirname, './src/loaders')],
        // 别名
        // alias: {
        //     loader1: path.resolve(__dirname, './src/loaders', 'loader1')
        // }
    },
    module: {
        rules: [{
            test: /\.js$/,
            use: ['loader1', 'loader2', 'loader3']
        }]
    }
}

如上我们引入loader的顺序从左到右是loader1、loader2、loader3,这时我们进行打包,输出的结果如下:

1650355316(1).png

所以得出结论:引用多个loader时,执行顺序是从右到左

我们换种引入方式,如下:

webpack.config.js 文件

const path = require('path');

module.exports = {
    mode: "development",
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    resolveLoader: {
        // 模块的查找顺序
        modules: ['node_modules', path.resolve(__dirname, './src/loaders')],
        // 别名
        // alias: {
        //     loader1: path.resolve(__dirname, './src/loaders', 'loader1')
        // }
    },
    module: {
        rules: [{
            test: /\.js$/,
            use: 'loader1',
        }, {
            test: /\.js$/,
            use: 'loader2'
        }, {
            test: /\.js$/,
            use: 'loader3'
        }]
    }
}

如上我们从上到下依次应用的顺序是loader1、loader2、loader3,这时我们进行打包,输出的结果如下:

1650355316(1).png

所以得出结论:引用多个loader时,执行顺序是从下到上

因此得出结论:loader的加载顺序是从下到上,从右到左!!!

# loader 的分类

loader在引入的时候默认都是normal即正常执行,总共有三种标识:

  1. pre:先执行
  2. normal:正常执行
  3. post:后执行

而这写标识需要在引入loader的时候,通过enforce来指定,如下:

module: {
    rules: [{
        test: /\.js$/,
        use: 'loader1',
        enforce: 'pre'
    }, {
        test: /\.js$/,
        use: 'loader2'
    }, {
        test: /\.js$/,
        use: 'loader3',
        enforce: 'post'
    }]
}

以上代码我们知道执行新顺序是从下到上loader3、loader2、loader1,但我们加上了enforce标识,改变了他们原有的执行顺序,这时再去执行则结果如下:

1650356286.png

是不是很神奇,和原来的执行顺序不一样了,所以我们可以后是开发工作中可根据需要通过enforce属性指定loader的不同执行顺序。

# 行内loade与特殊符号

其实除了上述的三种执行顺序外还有一种叫inline-laoder行内的loader,他们之间的执行顺序为:pre > normal > inline-loader > post, 我们来验证下

创建inline-loader.js文件,如下:

function loader(source) {
    console.log('我是inline-loader');

    return source;
}
module.exports = loader

在入口文件里引入一个js文件,并使用inline-loader去解析,如下:

const B = require('inline-loader!./b');

console.log('我是入口文件')

inline-loader!./b 分为三部分:inline-loader、!、./b,意思就是叹号后边的js文件./b需要通过inlin-loader来解析,运行打包代码,输出如下:

1650357207(1).png

开可以做些处理:希望匹配到inline-loader的时候,prenormal不再执行可以加一个-!,如下:

const B = require('-!inline-loader!./b');

这时执行打包时输入如下:

1650357512(1).png

像这种特殊符号我们有三种,如下:

  1. -!:不会让文件再去通过pre + normal loader处理
  2. !:不会让文件再去通过normal loader处理
  3. !!:只让inline-loader来处理

大家可以试下不同的符号处理的结果,nice ~~