devtool配置sourceMap
-
inline 不生成单独的sourceMap文件,而是直接打包进js文件里
-
module 映射第三方和loader的代码
-
cheap 只映射到出错行,不精确到列;只映射业务代码
-
eval 速度最快,但不全面
-
development: 建议cheap-module-eval-source-map
-
production: 默认不加最好,需要调试建议cheap-module-source-map
loader是什么
webpack只能理解JavaScript和JSON文件。loader让webpack能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。
常见loader
- file-loader: 将图片等文件打包进去
- url-loader: 将图片等文件打包进去,如果文件小于字节限制,返回DataURL
rules: [
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
}
]
- style-loader css-loader postcss-loader less-loader:
执行顺序从右到左
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader','postcss-loader','less-loader'],
},
]
- babel-loader:
将es6的新语法转换成es5代码,而不转换api。例如const、let、箭头函数会转换,但是Promise、Generator、Set、Proxy、Symbol等全局变量不会转换,可在main.js使用import @babel/polyfill在全局添加原生方法解决。
// 业务代码中
rules: [
{
test: /\.js$/,
exclude: /node_modules/,//不转化node_modules外部依赖,加快打包速度
use: {
loader: "babel-loader",
options: {
presets: [
[
"@babel/preset-env",
{
targets: {
chrome: "67",// 超过此版本无需再转换
ie: "11"
},
useBuiltIns: "usage" //polyfill仅添加用到的全局api(按需引入)
}
]
]
},
}
}
]
// polyfill会造成全局变量污染,所以开发类库的时候,换一种闭包导入形式的写法
rules: [
{
test: /\.js$/,
exclude: /node_modules/,//不转化node_modules外部依赖,加快打包速度
use: {
loader: "babel-loader",
options: {
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": 2, // 需要安装 @babel/runtime-corejs2 仅支持全局变量如Promise和静态属性如Array.from
"helpers": true,
"regenerator": true,
"useESModules": false,
}
]
]
},
}
}
]
编写一个loader
//replaceLoader
const loaderUtils = require('loader-utils')
module.exports = function(source){
const options = loaderUtils.getOptions(this);
return source.replace('name',options.name);
}
//webpack.config.js
rules: [
{
test: /\.js$/,
use: [
{
loader: path.resolve(__dirname,'./loaders/replaceLoader.js'),
options: {
name: 'you name'
}
}
]
}
]
plugin是什么
主要的作用是根据webpack提供的一些hooks钩子函数来进行一些额外的操作。
常见plugin
- html-webpack-plugin 在打包结束后自动生成一个html文件,并把生成的js文件引入
plugins: [new HtmlWebpackPlugin({
template:'src/index.html'
})]
- clean-webpack-plugin 在打包之前清理文件夹
plugins: [new CleanWebpackPlugin(['dist'])]
- ProvidePlugin
shimming垫片
const webpack = require('webpack')
plugins:[
new webpack.ProvidePlugin({
$:'jquery', //如果某js用到了$, 则自动在该js头部引入jq
_:'lodash'
})
]
编写一个plugin
class CopyrightWebpackPlugin{
apply(compiler){
compiler.hooks.emit.tapAsync('CopyrightWebpackPlugin',(compilation,cb)=>{
compilation.assets['copyright.txt']={
source:function(){return '123456789'},
size:function(){return 9}
}
cb();
});
}
}
module.exports = CopyrightWebpackPlugin
tree shaking 是什么?原理?
- tree shaking必须遵循ES6的模块规范(import & export),如果是CommonJS规范(require)则无法使用。
- webpack对代码进行标记,把import & export标记为3类:
- 所有import标记为 /* harmony import */
- 被使用过的export标记为 /* harmony export ([type]) */,其中 [type] 和webpack内部有关,可能是 binding, immutable 等等。
- 没被使用过的import标记为 /* unused harmony export [FuncName] */,其中 [FuncName] 为 export 的方法名称
- 之后在Uglifyjs(或者其他类似的工具)步骤进行代码精简,把没用的都删除。
code splitting 是什么?原理?
webpack多页面打包配置
- entry里面key-页面名称,value-js文件地址
- plugins里面为每个入口文件new HtmlWebpackPlugin()
const HtmlWebpackPlugin = require("HtmlWebpackPlugin");
const glob = require("glob");
const htmlPluginArray = [];
const entry = {};
glob.sync('./src/pages/*/index.js').forEach(function (filePath) {
let name = filePath.match(/\/pages\/(.+)\/index.js/);
name = name[1];
entry[name] = filePath;
htmlPluginArray.push(new HtmlWebpackPlugin({
filename: `./${name}/index.html`,
template: './src/index.html',
chunk: ['vendors','chunk',name],
}))
});
module.exports={
entry:entry,
plugins:[...htmlPluginArray],
output: {
publicPath: 'http://cdn.com',
filename: '[name].[contenthash].js',
chunkFilename: '[name]_[contenthash].js',
path: 'dist dir',
},
}
webpack 的热更新是如何做到的?说明其原理?
webpack如何优化项目体积
如何提升webpack的打包速度
- 更新webpack\node\npm版本
- 在尽可能少的模块上应用loader
例如babel-loader exclude
rules: [
{
test: /\.js$/,
exclude: /node_modules/,//不转化node_modules外部依赖,加快打包速度
use: {
loader: "babel-loader",
}
}
]
- Plugin尽可能少并确保可靠
- 使用DllPlugin提升webpack打包速度