前言:科大讯飞面试总结
1、webpack,http,软件工程
2、整理好自己的项目,流畅的介绍
3、框架以及技术选型,说出自己的见解。
4、先找几个公司练练手,一开始就不要去心仪的公司
5、花三个月准备一下算法,常用的
6、自我规划,以及梳理自己的知识体系,按照体系补充
7、基础的js和css知识点还是要去记一下
娱乐娱乐:https://mp.weixin.qq.com/s/y2CmMBIeiky5tu26GyQGww
多点看书,多点做笔记,看点积累,多点实践!!!
坚持输出自己
的代码,不要盲目的扎进公司业务
vscode 前端常用插件:https://www.cnblogs.com/xfcao/p/12729365.html
手写webpack loader
手写webpack plugin
"webpack":"^4.30.0",
"webpack-cli":"^3.3.0", //搭配webpack 的脚手架工具
"webpack-dev-server":"^3.7.2" //webpack开发服务器工具
1、在webpack构建流程中的特定时期注入扩展逻辑来改变构建结果或者做你想做的事情
可以接触到webpack构建流程中的各个阶段并劫持做一些代码处理,如自动生成HTML模板,自动压缩图片等
2、一个插件应该包含
(1)一个JS函数或者类,用于承接这个插件模块所有逻辑
(2)原型上定义apply方法,会在安装插件时就被webpack compiler调用一次
(3)指定一个触及到webpack本身的事件钩子,即hooks,用于特定实际处理额外的逻辑
(4)对webpack内部实例做一些操作处理
(5)在功能完成后调用webpack提供的回调函数
3、找到合适的事件点去完成功能在开发插件时显得尤为重要
4、tapable:贯穿整个webpack,实现插件绑定与调用的库,主要是控制钩子函数的发布与订阅。控制着webpack的插件系.webpack的本质就是一系列的插件运行.参考:https://segmentfault.com/a/1190000017420937
5、compiler的所有钩子请参考:https://webpack.docschina.org/api/compiler-hooks/#hooks
6、事件流:webpack 中事件流机制使用了观察者模式
8、
(1)tap:同步钩子,使用时不可以包含异步调用,因为函数返回时异步逻辑有可能未执行完导致问题
compiler.hooks.compile.tap('MyWebpackPlugin', params => {
console.log('我是同步钩子')
});
(2)tapAsync:异步钩子,通过callback告知Webpack异步逻辑执行完毕
//在emit阶段,1秒后打印文件列表
compiler.hooks.emit.tapAsync('MyWebpackPlugin', (compilation, callback) => {
setTimeout(()=>{
console.log('文件列表', Object.keys(compilation.assets).join(','));
callback();
}, 1000);
});
(3)tapPromise:异步钩子,和tapAsync的区别是tapPromise通过Promise来告知webpack异步逻辑执行完毕
//将文件列表上传到CDN
compiler.hooks.afterEmit.tapPromise('MyWebpackPlugin', (compilation) => {
return new Promise((resolve, reject) => {
const filelist = Object.keys(compilation.assets);
uploadToCDN(filelist, (err) => {
if(err) {
reject(err);
return;
}
resolve();
});
});
});
案例
1、生成清单文件
class MyWebpackPlugin {
apply(compiler) {
compiler.hooks.emit.tapAsync('MyWebpackPlugin', (compilation, callback) => {
const manifest = {};
for (const name of Object.keys(compilation.assets)) {
manifest[name] = compilation.assets[name].size();
// 将生成文件的文件名和大小写入manifest对象
}
compilation.assets['manifest.json'] = {
source() {
return JSON.stringify(manifest);
},
size() {
return this.source().length;
}
};
callback();
});
}
}
module.exports = MyWebpackPlugin;
md-to-html-plugin
const {readFileSync} = require('fs');
const { resolve } = require('path');
const {compileHtml} = require('./compiler')
const INNER_MARK = '<!-- inner -->'
class MdToHtmlPlugin{
constructor({template,filename}){
if(!template){
throw new Error('The config fro "template" must be configured')
}
this.template = template
this.filename = filename?filename:'md.html'
}
//apply是入口方法
apply(compiler){
console.log('compiler',compiler)
/**
* compiler.hooks.someHook.tap()
* compiler钩子类型
* emit :输出 asset 到 output 目录之前执行,更改的最后机会
* SyncHook:同步钩子
* AsyncSeriesHook:异步钩子。
*/
//compiler 可以看成时webpack实例,全局唯一,代表webpack从启动到关闭的生命周期(webpack5中允许多个实例存在)
//webpack运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
//第一个参数支持对象格式
/**
* {
name:'md-to-html-plugin', 必须
before:''| [] | string=>xxxplugin.name,注册的插件在哪些插件的前面
stage:0,权重:权重大的排在事件管理中心的后面,默认是0
}
*
*/
compiler.hooks.emit.tap('md-to-html-plugin',(compilation) => {
/***
* tap:同步钩子
* tapAsync :异步钩子,通过callback回调告诉Webpack异步执行完毕
* tapPromise:异步钩子,返回一个Promise告诉Webpack异步执行完毕
*
*/
//compilation 包含了当前的模块资源,编译生成资源,变化的文件等,代表一次单独的编译,也提供了很多事件回调供插件做扩展
//compilation.assets:由chunk生成的输出文件名的键值对
/**
*对于同步的hook,需要使用tap挂载插件
* 对于异步的hook AsyncSeries,可以使用tap,tapAsync,taoPromise,需要回调
* 对于AsyncParallel ,可以使用tap,tapAsync,tapPromise,需要回调(resolve)
*/
const _assets = compilation.assets;
const _mdContent = readFileSync(this.template,'utf8')
const _templateHtml = readFileSync(resolve(__dirname,'template.html'),'utf8')
const _mdContentArr = _mdContent.split('\n')
const _htmlStr = compileHtml(_mdContentArr)
const _resHtml = _templateHtml.replace(INNER_MARK,_htmlStr)
// console.log('compilation',compilation)
_assets[this.filename] = {
source (){
return _resHtml
},
size (){
return _resHtml.length
}
}
})
}
}
module.exports = MdToHtmlPlugin
loader
- 一个模块化打包工具,默认只能处理js文件。因为其他文件没有模块化的概念。就需要把其他类型的文件转换为webpack能够识别处理的模块,loader就是在打包之前必须将其他文件转换为webpack能够识别处理的模块;常用的有css-loader处理css文件,解析css文件中的@import ,然后将文件内容复制过来替代@import,最后编译成commjs 模块加载到js
- file-loader :打包 图片以及字体图标等文件,使用的时候 import img from ‘./file.png’
- style-loader:将样式放入head中,可以结合 插件将css打包成单独的文件
- less ,sass :处理less sass 文件为css
- PostCSS-loader : 使用插件去转换css的工具,比如 autoprefixer(自动补全浏览器前缀)、postcss-pxtorem(自动把px代为转换成rem),postcss-preset-env 提供css的兼容性解决方案;必须放在css规则的最后,也就是最先执行; 且可以指定需要兼容的浏览器,在pacage.json中添加 browserlist
- 顺序 : [style-loader,css-loader,less-loader,PostCSS-loader]
- url-loader: 可以配置limit ,小于这个limit 的图片会被转换为base64,优点是请求变少了,缺点是打包的文件会变大,因为base64要大一些;默认使用es6moudle解析,可以关闭后使用commjs解析,具体配置:esModule:false,
- html-loader:处理html中引入的图片 ,默认就是使用commjs解析
- babel-loader:兼容js,需要下载@babel/core,@babel/preset-env,可以配置preset,指定兼容到哪个版本的浏览器,只能转换基本语法,promise不能转换;@babel/polyfill 可以兼容所有的js,但是打包文件很大
image-webpack-loader或img-loader 压缩图片
plugin
mini-css-extract-plugin,替代style-loader,将css打包成单独的文件
html-webpack-plugin 在打包结束之后自动创建一个index.html,是否压缩(默认不压缩)
new HtmlWebpackPlugin({
template:'./index.html',
minify:{
collapseEhitespase:true, //移除空格
removeComments:true, //移除注释
}
})
//压缩js , mode :'production'
clean-webpack-plugin 打包之前将指定的文件夹清空
- optimize-css-assets-webpack-plugin 压缩css
- commons-chunk-plugin :提取公共代码
- webpack-bundle-analyzer :可视化打包插件
- webpack-dev-server将我们打包好的程序运行在一个服务器环境下,可以解决企业开发中”开发阶段”的跨域问题,可以监听css js代码并自动刷新
babel/parser js代码转为AST, babel/generator ,AST转为js,babel/traverse遍历AST
常用优化配置
sourcemap 储存打包之后的文件和打包之前文件的依赖关系 ,生产环境生成 单独的soucemap文件,
- tree shaking 过滤没有使用的js 和css 代码
- Code-Splitting:将不经常修改的模块单独打包
- lazy-loading 异步加载
- Prefetching 空闲的时候加载js文件
- noParse 对于一些独立的库,不需要去分析他的依赖关系
- externals :将不会发生变化的第三方模块设置成扩展,避免将这些内容打包到我们的项目中, 从而提升打包速度,使用的时候直接使用?
- HappyPack开启多线程打包