webpack中loader是一个CommonJs风格的函数,接收输入的源码,通过同步或异步的方式替换源码后进行输出。
module.exports = function(source, sourceMap, meta) {
}
需要注意的是,该导出函数必须使用function,不能使用箭头函数,因为loader编写过程中会经常使用到this访问选项和其他方法。
我们先编写一个基本的Loader,完成的工作很简单,那就是把输出的字符串进行替换。
1.新建loader-example目录,执行npm初始化,并安装webpack
mkdir loader-example
cd loadeer-example
npm init -y
npm install webpack webpack-cli
2.构建项目目录
|----loader # loader目录
|----replace-loader.js # 替换字符串的Loader
|----src # 应用源码
|----index.js # 首页
|----package.json
|----webpack.config.js
3.编写loader/replace-loader.js
module.exports = function(source) {
return source.replace(/World/g, 'Loader');
};
本例中我们Loader只是简单的将源码中的”World“替换成了”Loader“。
4.编写src/index.js
console.log('Hello World');
5.编写webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index',
target: 'node', // 我们编译为Node.js环境下的JS,等下直接使用Node.js执行编译完成的文件
output:{
path: path.resolve(__dirname, 'build'),
filename: '[name].js'
},
module:{
rules:[
{
test:/\.js$/,
use: 'replace-loader'
}
]
},
resolveLoader: {
modules: ['./node_modules', './loader'] // 配置loader的查找目录
}
};
6.编写package.json
{
"scripts":{
"build":"webpack"
}
}
7.执行构建
npm run build
8.构建完成后,执行build/main.js
node build/main.js
此时终端输出如下,我们编写的Loader工作正常。
Hello Loader
我们使用第三方loader时经常可以看到传递选项的情况:
{
test:/\.js$/,
use:[
{
loader:'babel-loader',
options:{
plugins:['@babel/transform-runtime'],
presets:['@babel/env']
}
}
]
}
在Loader编写时,Webpack中官方推荐通过loader-utils来读取配置选项,我们需要先安装。
npm install loader-utils
我们给刚才编写的replace-loader传递一个选项,允许自定义替换结果。
const loaderUtils = require('loader-utils');
module.exports = function(source) {
const options = loaderUtils.getOptions(this);
return source.replace(/World/g, options.text);
};
接下来编辑webpack.config.js,给replace-loader传递选项。
module.exports = {
module:{
rules:[
{
test:/\.js$/,
use:[
{
loader:'replace-loader',
options:{
text: 'Webpack4'
}
}
]
}
]
},
resolveLoader:{
modules: ['./node_modules', './loader']
}
};
执行构建之后用Node.js执行build/main.js,可以看到输出的内容已经发生变化了。
Hello Webpack4
在Loader中,如果存在异步调用,那么就无法直接通过return返回构建后的结果了,此时需要使用到Webpack提供的回调函数将数据进行回调。
Webpack4给Loader提供了this.async()函数,调用之后返回一个callback,callback的签名如下:
function callback(
err: Error|null,
content: string|Buffer,
sourceMap?:SourceMap,
meta?: any
)
例如我们需要在loader中调用setTimeout进行等待,则相应的代码如下:
module.exports = function(source) {
const callback = this.async();
setTimeout(() => {
const output = source.replace(/World/g, 'Webpack4');
callback(null, output);
}, 1000);
}
执行构建,Webpack会等待一秒,然后再输出构建内容,通过Node.js执行构建后的文件,输出如下
Hello Webpack4
默认情况下,资源文件会被转化为 UTF-8 字符串,然后传给 loader。通过设置 raw,loader 可以接收原始的 Buffer。比如处理非文本文件时(如图片等等)。
module.exports = function(source) {
assert(source instanceof Buffer);
return someSyncOperation(source);
};
module.exports.raw = true; // 设置当前Loader为raw loader, webpack会将原始的Buffer对象传入
babel-loader在使用时可以加载.babelrc配置文件来配置plugins和presets,减少了webpack.config.js的代码量,便于维护。接下来我们编写一个i18n-loader,通过读取语言配置文件完成语言转换。
|----loader
|----i18n-loader.js # loader
|----i18n
|----zh.json # 中文语言包
|----src
|----index.js # 入口文件
|----webpack.config.js
i18n/zh.json
{
"hello": "你好",
"today": "今天"
}
loader/i18n-loader.js
const loaderUtils = require('loader-utils');
const path = require('path');
module.exports = function (source) {
const options = loaderUtils.getOptions(this);
const locale = options ? options.locale : null;
// 读取语言配置文件
let json = null;
if (locale) {
const filename = path.resolve(__dirname, '..', 'i18n', `${locale}.json`);
json = require(filename);
}
// 读取语言标记 {{}}
const matches = source.match(/\{\{\w+\}\}/g);
for (const match of matches) {
const name = match.match(/\{\{(\w+)\}\}/)[1].toLowerCase();
if (json !== null && json[name] !== undefined) {
source = source.replace(match, json[name]);
} else {
source = source.replace(match, name);
}
}
return source;
}
src/index.js
console.log('{{Hello}}, {{Today}} is a good day.');
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index',
output: {
path: path.resolve(__dirname, 'build'),
filename: '[name].js'
},
target: 'node',
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'i18n-loader',
options: { // 传递选项
locale: 'zh'
}
}
]
}
]
},
resolveLoader: {
modules: ['./node_modules', './loader']
}
};
package.json
{
"scripts":{
"build":"webpack"
}
}
npm run build
构建完毕后使用Node.js执行build/main.js输出如下:
你好, 今天 is a good day.
可以看到i18n-loader成功读取了配置文件。
webpack 在前端工程中随处可见,当前流行的 vue, react, weex 等解决方案都推崇 webpack 作为打包工具。前端工具云集的时代,这是你值得选择的之一。
webpack是前端工程构建的一套工具,为什么一个程序称之为一套呢,是因为webpack其实是npm的一个模块,使用起来的话,这期间还需要很多其它模块来进行支持,所以我称之为一套工具。
本文从一个小Demo开始,通过不断增加功能来说明webpack的基本配置,只针对新手。webpack基本的配置就可以熟悉了,会引入loader,配置loader选项,会设置alias,会用plugins差不多。
Plugins是webpack的基础,我们都知道webpage的plugin是基于事件机制工作的,这样最大的好处是易于扩展。讲解如果扩展内置插件和其他插件,以及我们常用的Plugins插件
webpack技巧的总结:进度汇报、压缩、复数文件打包、分离app文件与第三方库文件、资源映射、输出css文件、开发模式、分析包的大小、更小的react项目、更小的Lodash、引入文件夹中所有文件、清除extract-text-webpack-plugin日志。
Webpack 作为目前最流行的前端构建工具之一,在 vue/react 等 Framework 的生态圈中都占据重要地位。在开发现代 Web 应用的过程中,Webpack 和我们的开发过程和发布过程都息息相关,如何改善 Webpack 构建打包的性能也关系到我们开发和发布部署的效率。
新版 Webpack 中我们所做的每一个更新目的都在于此,为了当大家在使用 Webpack 的时候敏捷连续毫无顿挫感。 webpack 4 进行构建性能测试,得出的结果非常有趣。结果很惊人,构建时间降低了 60%-98%!
Webpack 是一个现代 JavaScript 应用程序的模块打包器 (module bundler) 。当 Webpack 处理应用程序时,它会递归地构建一个依赖关系图,其中包含应用程序需要的每个模块
Tobias Koppers是一位自由软件开发者,家住德国纽伦堡。他因写出webpack这个已有数百万开发者使用的开源软件而名噪一时。他目前专注于JavaScript和开源项目。以下是我对他个人的专访,希望对大家有所启发。
本文讲述css-loader开启css模块功能之后,如何与引用的npm包中样式文件不产生冲突。比如antd-mobilenpm包的引入。在不做特殊处理的前提下,样式文件将会被转译成css module。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!