前言
咱们先思考一个问题:如果不应用 webpack,前端可能开发我的项目吗?
先别着急说出答案,咱们持续往下看 …
工作中,咱们都是应用框架的脚手架进行开发,支流的趋势 …
vue-cli & create-react-app 和 webpack 的关系
咱们晓得,无论是 Vue 的 vue-cli 还是 React 的 create-react-app 这样的脚手架,实际上都是给 webpack 做了一层封装,包了一层壳子,并预设了一些默认罕用的配置项(当然还有别的货色),以便晋升开发效率。
所以它们的关系是:脚手架只是给 webpack 穿上了一个马甲 …
不过有时候脚手架提供的默认配置项不够用了,就须要咱们手动去写一些 plugin 或者 loader 从而实现咱们想要的性能。
学习本文的播种
- 通俗易懂地回顾 webpack 知识点
- 学习在 vue-cli 脚手架中写 webpack 的 plugin 的知识点
- 学习在 vue-cli 脚手架中写 webpack 的 loader 的知识点
webpack
平时咱们写代码都是
模块化、组件化(工程化)
进行开发,导致代码会进行拆分、细化、公共局部提取、援用等 …
为何要 模块化、组件化(工程化)
进行开发呢?因为:这是软件开发的支流和趋势 …
什么是 webpack & 谈谈你对 webpack 的了解
- 平时咱们写代码都是
模块化、组件化(工程化)
进行开发,导致代码会进行拆分、细化、公共局部提取、援用等 … - 比方:咱们会写很多.vue 文件(当然还有别的文件如.less 等)。然而咱们写的代码是最终要被浏览器拜访解析执行的,而浏览器不意识.vue 文件,也不意识.less 文件!
- 浏览器不意识就不能解析,不能用。
- 浏览器倒是意识 js、css、html,能够解析出相应内容,并渲染展现。
- 又因为 .vue 文件和.less 文件实际上也只是 html、css、js
化妆之后
的款式。 - 那这样,搞一个工具,可能让.vue 文件和.less 文件
卸妆
成 html、css、js 就行了。 - 而 webpack 恰好可能做到这一点(编译转化打包)
所以,webpack 就是:一个转化编译打包工具,将一些浏览器不意识的花里胡哨的文件转化为浏览器意识的 html、css、js 文件。
还记得咱们最终打包好的 dist 文件夹目录吗?外面就只有:
html、css、js 等
一些资源 …这样形容,不是非常谨严。精确来说,webpack 是一个动态模块资源打包工具,官网:https://webpack.docschina.org/concepts/
回到最开始的那个问题~
如果不应用 webpack,前端可能开发我的项目吗?
- 问:如果不应用 webpack,前端可能开发我的项目吗?
- 答:如果一个我的项目炒鸡小,只是用来展现一点点货色,齐全能够应用原生的 html、css、js 去写,这样的话,就用不到
咱们要晓得 webpack 的作用就是,去转化编译打包脚手架、工程化的大我的项目。如果是一个小我的项目,齐全不须要去用工程化的形式开发,间接写,写完了丢到服务器上,间接用
前端工程化 == 模块化 + 组件化 + 自动化 + …
webpack 的几个重要概念
- 打包入口(entry)
- 打包输入(output)
- 加载器(loader)
- 插件(plugin)
- 模式(mode)
- nodejs 环境(environment)
webpack 打包入口 -entry
- 咱们晓得,咱们开发我的项目有很多文件,比方 a、b、c 等。a 援用了 b 中的货色,而 b 又援用了 c 中的货色。那么打包翻译的话,就须要指定从哪个文件开始打包,打包的过程中如果遇到了有别的援用,就顺藤摸瓜 …
- webpack 中默认打包的入口文件是
./src/index.js
文件,这个文件中援用了好多别的文件,所以 webpack 持续顺藤摸瓜寻找、编译、转化、打包。 - 而 vue-cli 脚手架中的入口文件是 src 目录下的 main.js 文件(vue-cli 改写了 webpack 默认的入口文件地位罢了)
- 这里咱们能够去 vue-cli 仓库代码中去找到相干的代码,能看到指定的打包入口
vue-cli 仓库地址:https://github.com/vuejs/vue-cli
大家把代码下载下来,Code –> Download ZIP,而后在 vscode 中关上代码,在左上角第二个放大镜中搜寻关键字:src/main.js
有很多的关键词,其中有一个 get entryFile
办法,代码如下:
/**
* Get the entry file taking into account typescript.
*
* @readonly
*/
get entryFile () {if (this._entryFile) return this._entryFile
return (this._entryFile = fs.existsSync(this.resolve('src/main.ts')) ? 'src/main.ts' : 'src/main.js')
}
对应截图如下:
其实 vue-cli 中有很多的中央的代码,都告知了咱们 vue-cli 是将 main.js 作为 webpack 打包的入口的,大家多看看 …
好了,至此咱们见证了 webpack 的打包入口 (entry) 在 vue-cli 脚手架中的具体利用展示模式。大家也能够在 create-react-app 中去看一下 webpack 的打包入口文件,一个意思
vue-cli
和webpack
的关系,换句话说,也像苹果手机
和富士康
的关系 …
webpack 打包输入 -output
咱们晓得,平时我的项目写完,公布上线,打包输入的个别都是一个 dist 文件夹(也能够改)
原始的 webpack 是这样写:
const path = require('path');
module.exports = {
entry: './src/index.js', // 从以后同级目录下的 index.js 作为入口文件,顺藤摸瓜开始打包
output: {path: path.resolve(__dirname, 'dist'), // 这里的 path 值要是一个绝对路径,如:E:\echarts\code\dist,所以要应用 path 模块来操作
filename: 'myDemo.js',
},
};
vue-cli 中叫做 outputDir 并指定了默认值为 dist(实际上就是 webpack 中的 output,又是套壳子),咱们通过在 vue.config.js 文件中更改 outputDir 的值,即可批改打包换名字了
vue-cli 中的代码如下:
exports.defaults = () => ({
// project deployment base
publicPath: '/',
// where to output built files
outputDir: 'dist', // 即为 webpack 中的 output
// where to put static assets (js/css/img/font/...)
assetsDir: '',
// filename for index.html (relative to outputDir)
indexPath: 'index.html',
// ......
devServer: {
/*
open: process.platform === 'darwin',
host: '0.0.0.0',
port: 8080,
https: false,
hotOnly: false,
proxy: null, // string | Object
before: app => {}
*/
}
})
留神看,上述的参数,就是 vue.config.js 须要咱们设定的一些参数
vue-cli 中的 webpack 工作流程
- 咱们在 vue.config.js 中写的合乎 vue-cli 语法的代码,会被传递到 vue-cli 代码中
- vue-cli 接管到当前,会再转化一下,转化成为合乎 webpack 语法的配置
- 并通过 webpack-merge 这个插件,传递给 webpack 中。
- webpack 拿到对应配置项当前,再执行相应的打包策略形式
create-react-app 这个脚手架也是相似,大抵都是套壳子,定规定,拿参数(解决),丢给 webpack 去打包
模式(mode)
- 开发模式(development)
- 生产模式(production)
nodejs 环境(environment)
咱们晓得 webpack 是用 js 语言写的,在 nodejs 创立的环境中运行,咱们能够通过我的项目中的 node_modules/webpack/bin/webpack.js 文件看到 如下图,看一下:
child_process 为 node 的子过程
高深莫测 …
webpack 工作流程
在 nodejs 环境下,从入口递归寻找各个模块(组件)依赖关系,去打包,遇到不能间接辨认的比方.vue 文件、.less 文件,就应用对应的 loader 去解析它。另外如果还能够在 webpack 的生命周期钩子的某一个工夫节点,去操作打包的内容,从而管制打包的后果。
vue.config 配置 webpack 插件的办法,对象写法或函数写法
实际上,学习 webpack 学的就是,别的开发者或者公司去开发的 loader 或者 plugin,学的是 webpack 的生态。
webpack 加载器 -loader
什么是 loader
loader 顾名思义,就是加载的意思,加载什么呢?加载 webpack 不能间接意识的文件,加载好当前,以供 webpack 去打包。
webpack 间接意识的只有 js 和 json 文件内容
有哪些常见的 loader
- vue-loader 去加载.vue 文件
- react-loader 用于加载 react 组件的
- style-loader 将 css 款式挂到 style 标签下
- css-loader 编译 css 款式文件
- less-loader 去加载.less 款式文件
- postcss-loader 给款式加上浏览器前缀
- file-loader 和 url-loader 能够压缩图片资源(后者可压成 base64)
- babel-loader、ts-loader、eslint-loader 等
loader 执行程序
从下到上,从右到左。
简略的 loader 之去除 console.log
第一步,src 目录下新建文件夹 myLoader,内创立 js 文件 removeConsole.js 文件
一个 loader 就是一个模块化的 js 文件
第二步,裸露一个函数,loader 实质上是一个函数,在函数体外部,能够去对代码(字符串)进行加工
plugin 也是相似,也能够对代码字符串进行加工,不过性能更加弱小
第三步,写 loader 函数逻辑内容
const reg = /(console.log\()(.*)(\))/g;
module.exports = function (source) {console.log('source', source);
source = source.replace(reg, "")
return source;
}
loader 就是一个加工函数,回想起 js 中的经典的一句话,万物皆可函数
第四步,在 vue.config.js 中的 configureWebpack 中增加应用本人写的 loader
/**
* 增加本人写的模块 loader
* */
module: {
rules: [
/**
* 对.vue 和.js 文件失效,不蕴含 node_modules 大文件夹,加载器的地位在
* 当前目录下的./src/myLoader/removeConsole.js
* */
// {
// test: /\.vue$/,
// exclude: /node_modules/,
// loader: path.resolve(__dirname, "./src/myLoader/removeConsole.js")
// },
// {
// test: /\.js$/,
// exclude: /node_modules/,
// loader: path.resolve(__dirname, "./src/myLoader/removeConsole.js")
// }
],
}
如果想要给 loader 传参,接参,能够在 loader 函数外部应用 this.query 接管,或者 npm i -D loader-utils 工具包去进一步操作。
残缺代码示例,见 GitHub 仓库:https://github.com/shuirongshuifu/elementSrcCodeStudy
更多开发 loader 细节,见官网文档:
webpack 插件 -plugin
什么是 plugin
- loader 解决不了的,去应用 plugin 去解决
- webpack 在打包资源代码文件时,也会有先后执行步骤,换句话说即为 webpack 的生命周期
- 所以咱们能够在对应生命周期的钩子函数中,去编写一些代码从而影响最终的打包后果
- 这些编写的代码,即为 webpack 的插件(代码)
webpack 的打包也会有很多生命周期,plugin 就是在适合的机会,通过 webpack 提供的 api,去扭转输入后果。留神,loader 是一个转换器,运行在打包之前,而 plugin 在整个编译周期都起作用。
plugin 构造
- plugin 是一个 class 类(构造函数)
- 类中的 constructor 函数用来接参
- apply 函数的 compiler 对象自带很多的 api 能够供咱们调用
- 通过这些 api 的应用最终影响打包后果
如下代码:
class myPlugin {constructor(options) {console.log("接参 -->", options);
}
apply(compiler) {console.log('下面有十分多 api,可参见 compiler 打印后果', compiler)
}
}
module.exports = myPlugin
打印的 compiler 对象
通过下方的打印后果,咱们确实能够看到 compiler.hooks.xxx 有很多暴露出的 api
实际上去编写 webpack 中的 plugin 就是,去正当应用 Compiler 的相干 hooks
Compiler {
_pluginCompat: SyncBailHook {_args: [ 'options'],
taps: [[Object], [Object], [Object] ],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
// 钩子函数,即为生命周期
hooks: {
shouldEmit: SyncBailHook {_args: [Array],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
done: AsyncSeriesHook {_args: [Array],
taps: [Array],
interceptors: [],
call: undefined,
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
additionalPass: AsyncSeriesHook {_args: [],
taps: [Array],
interceptors: [],
call: undefined,
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
beforeRun: AsyncSeriesHook {_args: [Array],
taps: [Array],
interceptors: [],
call: undefined,
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
run: AsyncSeriesHook {_args: [Array],
taps: [],
interceptors: [],
call: undefined,
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
emit: AsyncSeriesHook {_args: [Array],
taps: [Array],
interceptors: [Array],
call: undefined,
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
assetEmitted: AsyncSeriesHook {_args: [Array],
taps: [],
interceptors: [],
call: undefined,
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
afterEmit: AsyncSeriesHook {_args: [Array],
taps: [Array],
interceptors: [Array],
call: undefined,
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
thisCompilation: SyncHook {_args: [Array],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
compilation: SyncHook {_args: [Array],
taps: [Array],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
normalModuleFactory: SyncHook {_args: [Array],
taps: [Array],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
contextModuleFactory: SyncHook {_args: [Array],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
beforeCompile: AsyncSeriesHook {_args: [Array],
taps: [],
interceptors: [],
call: undefined,
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
compile: SyncHook {_args: [Array],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
make: AsyncParallelHook {_args: [Array],
taps: [Array],
interceptors: [],
call: undefined,
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
afterCompile: AsyncSeriesHook {_args: [Array],
taps: [],
interceptors: [],
call: undefined,
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
watchRun: AsyncSeriesHook {_args: [Array],
taps: [],
interceptors: [],
call: undefined,
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
failed: SyncHook {_args: [Array],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
invalid: SyncHook {_args: [Array],
taps: [Array],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
watchClose: SyncHook {_args: [],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
infrastructureLog: SyncBailHook {_args: [Array],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
environment: SyncHook {_args: [],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
afterEnvironment: SyncHook {_args: [],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
afterPlugins: SyncHook {_args: [Array],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
afterResolvers: SyncHook {_args: [Array],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
entryOption: SyncBailHook {_args: [Array],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
infrastructurelog: SyncBailHook {_args: [Array],
taps: [],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
}
},
name: undefined,
parentCompilation: undefined,
outputPath: '',
outputFileSystem: NodeOutputFileSystem {mkdirp: [Function: mkdirP] {mkdirP: [Circular],
mkdirp: [Circular],
sync: [Function: sync]
},
mkdir: [Function: bound mkdir],
rmdir: [Function: bound rmdir],
unlink: [Function: bound unlink],
writeFile: [Function: bound writeFile],
join: [Function: bound join]
},
inputFileSystem: CachedInputFileSystem {fileSystem: NodeJsInputFileSystem {},
_statStorage: Storage {
duration: 60000,
running: Map {},
data: Map {},
levels: [Array],
count: 0,
interval: null,
needTickCheck: false,
nextTick: null,
passive: true,
tick: [Function: bound tick]
},
_readdirStorage: Storage {
duration: 60000,
running: Map {},
data: Map {},
levels: [Array],
count: 0,
interval: null,
needTickCheck: false,
nextTick: null,
passive: true,
tick: [Function: bound tick]
},
_readFileStorage: Storage {
duration: 60000,
running: Map {},
data: Map {},
levels: [Array],
count: 0,
interval: null,
needTickCheck: false,
nextTick: null,
passive: true,
tick: [Function: bound tick]
},
_readJsonStorage: Storage {
duration: 60000,
running: Map {},
data: Map {},
levels: [Array],
count: 0,
interval: null,
needTickCheck: false,
nextTick: null,
passive: true,
tick: [Function: bound tick]
},
_readlinkStorage: Storage {
duration: 60000,
running: Map {},
data: Map {},
levels: [Array],
count: 0,
interval: null,
needTickCheck: false,
nextTick: null,
passive: true,
tick: [Function: bound tick]
},
_stat: [Function: bound bound],
_statSync: [Function: bound bound],
_readdir: [Function: bound readdir],
_readdirSync: [Function: bound readdirSync],
_readFile: [Function: bound bound readFile],
_readFileSync: [Function: bound bound readFileSync],
_readJson: [Function],
_readJsonSync: [Function],
_readlink: [Function: bound bound readlink],
_readlinkSync: [Function: bound bound readlinkSync]
},
recordsInputPath: null,
recordsOutputPath: null,
records: {},
removedFiles: Set {},
fileTimestamps: Map {},
contextTimestamps: Map {},
resolverFactory: ResolverFactory {
_pluginCompat: SyncBailHook {_args: [Array],
taps: [Array],
interceptors: [],
call: [Function: lazyCompileHook],
promise: [Function: lazyCompileHook],
callAsync: [Function: lazyCompileHook],
_x: undefined
},
hooks: {resolveOptions: [HookMap], resolver: [HookMap] },
cache2: Map {}},
infrastructureLogger: [Function: logger],
resolvers: {normal: { plugins: [Function: deprecated], apply: [Function: deprecated] },
loader: {plugins: [Function: deprecated], apply: [Function: deprecated] },
context: {plugins: [Function: deprecated], apply: [Function: deprecated] }
},
options: {
mode: 'development',
context: 'E:\\echarts\\code',
devtool: 'eval-cheap-module-source-map',
node: {
setImmediate: false,
process: 'mock',
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
console: false,
global: true,
Buffer: true,
__filename: 'mock',
__dirname: 'mock'
},
output: {
path: 'E:\\echarts\\code\\dist',
filename: 'js/[name].js',
publicPath: '/',
chunkFilename: 'js/[name].js',
globalObject: "(typeof self !=='undefined'? self : this)",
webassemblyModuleFilename: '[modulehash].module.wasm',
library: '',
hotUpdateFunction: 'webpackHotUpdate',
jsonpFunction: 'webpackJsonp',
chunkCallbackName: 'webpackChunk',
devtoolNamespace: '',
libraryTarget: 'var',
pathinfo: true,
sourceMapFilename: '[file].map[query]',
hotUpdateChunkFilename: '[id].[hash].hot-update.js',
hotUpdateMainFilename: '[hash].hot-update.json',
crossOriginLoading: false,
jsonpScriptType: false,
chunkLoadTimeout: 120000,
hashFunction: 'md4',
hashDigest: 'hex',
hashDigestLength: 20,
devtoolLineToLine: false,
strictModuleExceptionHandling: false
},
resolve: {alias: [Object],
extensions: [Array],
modules: [Array],
plugins: [Array],
unsafeCache: true,
mainFiles: [Array],
aliasFields: [Array],
mainFields: [Array],
cacheWithContext: true,
preferAbsolute: true,
ignoreRootsErrors: true,
roots: [Array]
},
resolveLoader: {modules: [Array],
plugins: [Array],
unsafeCache: true,
mainFields: [Array],
extensions: [Array],
mainFiles: [Array],
cacheWithContext: true
},
module: {noParse: /^(vue|vue-router|vuex|vuex-router-sync)$/,
rules: [Array],
unknownContextRequest: '.',
unknownContextRegExp: false,
unknownContextRecursive: true,
unknownContextCritical: true,
exprContextRequest: '.',
exprContextRegExp: false,
exprContextRecursive: true,
exprContextCritical: true,
wrappedContextRegExp: /.*/,
wrappedContextRecursive: true,
wrappedContextCritical: false,
strictExportPresence: false,
strictThisContextOnImports: false,
unsafeCache: true,
defaultRules: [Array]
},
optimization: {splitChunks: [Object],
minimizer: [Array],
removeAvailableModules: false,
removeEmptyChunks: true,
mergeDuplicateChunks: true,
flagIncludedChunks: false,
occurrenceOrder: false,
sideEffects: false,
providedExports: true,
usedExports: false,
concatenateModules: false,
runtimeChunk: undefined,
noEmitOnErrors: false,
checkWasmTypes: false,
mangleWasmImports: false,
namedModules: true,
hashedModuleIds: false,
namedChunks: true,
portableRecords: false,
minimize: false,
nodeEnv: 'development'
},
plugins: [VueLoaderPlugin {},
[DefinePlugin],
[CaseSensitivePathsPlugin],
[FriendlyErrorsWebpackPlugin],
[HtmlWebpackPlugin],
[PreloadPlugin],
[PreloadPlugin],
[CopyPlugin],
[HotModuleReplacementPlugin],
[ProgressPlugin],
HelloPlugin {}],
entry: {app: [Array] },
cache: true,
target: 'web',
performance: false,
infrastructureLogging: {level: 'info', debug: false}
},
context: 'E:\\echarts\\code',
requestShortener: RequestShortener {currentDirectoryRegExp: /(^|!)E:\/echarts\/code/g,
parentDirectoryRegExp: /(^|!)E:\/echarts\//g,
buildinsAsModule: true,
buildinsRegExp: /(^|!)E:\/echarts\/code\/node_modules\/_webpack@4\.46\.0@webpack/g,
cache: Map {}},
running: false,
watchMode: false,
_assetEmittingSourceCache: WeakMap {<items unknown>},
_assetEmittingWrittenFiles: Map {},
watchFileSystem: NodeWatchFileSystem {
inputFileSystem: CachedInputFileSystem {fileSystem: NodeJsInputFileSystem {},
_statStorage: [Storage],
_readdirStorage: [Storage],
_readFileStorage: [Storage],
_readJsonStorage: [Storage],
_readlinkStorage: [Storage],
_stat: [Function: bound bound],
_statSync: [Function: bound bound],
_readdir: [Function: bound readdir],
_readdirSync: [Function: bound readdirSync],
_readFile: [Function: bound bound readFile],
_readFileSync: [Function: bound bound readFileSync],
_readJson: [Function],
_readJsonSync: [Function],
_readlink: [Function: bound bound readlink],
_readlinkSync: [Function: bound bound readlinkSync]
},
watcherOptions: {aggregateTimeout: 200},
watcher: EventEmitter {_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
options: [Object],
watcherOptions: [Object],
fileWatchers: [],
dirWatchers: [],
mtimes: [Object: null prototype] {},
paused: false,
aggregatedChanges: [],
aggregatedRemovals: [],
aggregateTimeout: 0,
_onTimeout: [Function: bound _onTimeout]
}
}
}
简略的 plugin 写一个生成的动态资源文件
插件代码
class myPlugin {constructor(options) {// constructor 构造函数接管 new myPlugin(params)时传递的参数 params
console.log("我是 new 这个类时所传递的参数 -->", options);
}
apply(compiler) {// console.log('^_^', compiler) // 下面有十分多 api,可供使用(参见 compiler 打印后果)compiler.hooks.emit.tapAsync('lss',(compliation,cb)=>{console.log('compliation',compliation.assets);
const content=`
- 生存不易
- 打工仔加油致力
- 奥利给
- 😄😄😄
`
compliation.assets['FBI-WARNING.md'] = {size() {return content.length},
source: function () {return content}
}
cb()})
}
}
module.exports = myPlugin
vue.config.js 文件中应用插件
// 引入这个插件
const myPlugin = require('./src/plugin/myPlugin')
configureWebpack: {
// 在 plugins 数组中实例化对象,若须要传参,变传递参数
plugins: [new myPlugin('我是参数')
]
},
未完待续。明天就先写(水)到这里吧