合并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的特点

  1. 职责单一,一个loader只做一件事情,可以组合。
  2. loader的pitch函数可以中断执行,直接跳到最后一个loader执行。
  3. 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直接将文件拷贝到对应目录下。