合并webpack配置文件用哪个插件
webpack-merge
webpack.hotmodulereplace
允许在运行时更新所有类型的模块,而无需完全刷新,React组件更新用以下方式开启
// react-hot-loader模块看github文档,还需要安装一个babel插件
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'mobx-react'
import { useStrict } from 'mobx'
import { AppContainer } from 'react-hot-loader'
import styles from './styles/app.less'
import App from './app'
import injects from './inject'
// 不允许在@action之外进行状态的修改
useStrict(true)
//防止iframe嵌入
if (window.top !== window.self) {
location.href = '/'
}
const render = Component => {
ReactDOM.render(
<AppContainer>
<Provider {...injects}>
<Component/>
</Provider>
</AppContainer>,
document.getElementById('app')
)
}
render(App)
if (module.hot) {
module.hot.accept('./app', () => { render(App)})
}
像style-loader已经自己实现了这一功能,正常使用就可以了。
source-map开发和生产环节选择
scope-hosting做了什么?
分析静态文件,也就是必须用ES6的import,将一些明显的简单代码进行去除,去除函数声明,减小代码体积。
splitChunk可以做什么?
抽离node_modules里面的第三方模块作为vendor.js,配置条件作为抽离业务中的公共模块(比如文件大小,被引用次数等)
splitChunk和dllplugin如何一起使用?
如何去除moment.js中其他语言的包?
ignorePlugin
tapable是用来做什么的?
webpack基于这个库,拥有了一系列生命周期钩子, 比如打包前,打包后等,我们就可以编写插件在对应的生命周期来拓展我们想要等功能。
babel插件是怎么样的?
其实就是用babel
提供的ast操作工具库来对我们想改掉的语法类型进行转换。方法已经都很全封装好了,我们只需要按照他的api进行操作就可以。
总体流程就是:深度遍历ast树,当遍历到想要改变的节点时,进行转换,然后生成新的ast输出。在写插件的时候,就是分析转化前的树和转化后的树,然后用babel的api进行替换就可以了。
let code = `let fn = (a,b) => {return a+b}` // let fn = function(a,b){return a+b}
// @babel/core 调用 presets中的预设进行转化
let babel = require('@babel/core');
let t = require('@babel/types'); // 这个模块的作用 1) 判断这个node是不是这个node,生成对应的表达式
// 使用自己的插件来实现箭头函数的转化 (babel插件的写法 webpack可能会使用到babel插件)
let arrowFunction = { // 访问者模式
visitor:{ // 当访问到某个路径的时候进行匹配
ArrowFunctionExpression(path){
let node = path.node; // 取到对应的对象 通过路径获取
let params = node.params; // 获取当前函数的参数
let body = node.body; // 函数函数体
if(!t.isBlockStatement(body)){ // 如果当前有代码块了,就不处理了
// 否则声明一个代码块 返回以前的箭头函数的结果
body = t.blockStatement([t.returnStatement(body)])
}
let functionExpression = t.functionExpression(null,params,body);
// 用新的内容 替换掉老的内容
path.replaceWith(functionExpression);
}
}
}
let r = babel.transform(code,{ // escodegen 忽略掉
plugins:[
arrowFunction
// '@babel/plugin-transform-arrow-functions'
]
});
console.log(r.code);
path.resolve如果省略第一个参数会怎么样?
以当前执行路径为第一个参数。
loader和plugin的区别
loader就是给函数,plugin就是个类。
loader是对源码进行转化,在webpack内部逻辑,会匹配对应的文件,用loader进行处理对应的代码。而plugin更多的则是在各个打包周期添加更多的功能。比如每次打包删除代码,对代码分割的模块进行命名处理等等。
loader的特点
- 职责单一,一个loader只做一件事情,可以组合。
- loader的pitch函数可以中断执行,直接跳到最后一个loader执行。
- loader不能有状态,这样保证每个人通过同一个loader执行后的结果相同。
loader执行顺序
从右向左,从下到上。
pre-normal-inline-post
file-loader思路
import img from './img.jpg'
希望得到
module.exports = 'hash.jpg'
并且将该图片放到dist目录下。
代码思路:借助loader-utils,生成图片hash路径,使用webpack的this.emitFile api
直接将文件拷贝到对应目录下。