移动端css px自动转换成rem:
px2rem-loader:
{
loader: 'px2rem-loader',
options: {
remUnit: 75,
// 1个rem是多少px, 一般以750设计稿,
vw/10是75 remPrecision: 8
// rem计算保留8个小数点
} }
静态资源内联:
css内联:
方法一:借助style-loader:
{ loader: 'style-loader', options: { insert: 'top',
// 样式插入到<head>
injectType: 'singletonStyleTag',
// 将所有的style标签合并成一个 } } }
方法二:html-inline-css-webpack-plugin:
将<link rel="stylesheet" /> => <style>...<style/>
const HTMLInlineCSSWebpackPlugin = require('html-inline-css-webpack-plugin').default; ... plugins: [ new HTMLInlineCSSWebpackPlugin() ]
raw-loader: 只能安装0.5.1版本,否则会报错
html-webpack-plugin: html压缩的plugin.可以自动创建html模板组件,默认支持html、ejs, 其他模板引擎需要相关加载器。
<!DOCTYPE html> <html lang="en"> <head> ${ require('raw-loader!./meta.html') } <title>Document</title> <script>${ require('raw-loader!babel-loader!../node_modules/lib-flexible/flexible.js') }</script> </head> <body> <div id="root"></div> </body> </html>
多页面应用打包通用方案:
const glob = require('glob');
const setMPA = () => {
const entry = {};
const htmlWebpackPlugin = [];
const entryFiles = glob.sync(path.join(__dirname, './src/*/index.js'));
console.log('entryFiles', entryFiles);
Object.keys(entryFiles) .map((index) => {
const entryFile = entryFiles[index];
// '/Users/wangrui/workspace/tech/webpack-demos-jk/src/index/index.js'
const match = entryFile.match(/src\/(.*)\/index\.js/);
const pageName = match && match[1];
entry[pageName] = entryFile;
htmlWebpackPlugin.push( new HtmlWebpackPlugin({ template: path.join(__dirname, `src/${pageName}/index.html`), filename: `${pageName}.html`,
chunks: [pageName], inject: true, minify: { html5: true, collapseWhitespace: true, preserveLineBreaks: false, minifyCSS: true, minifyJS: true, removeComments: false } }), ); }) return { entry, htmlWebpackPlugin } }
const { entry, htmlWebpackPlugin } = setMPA();
...
plugins: [
new MiniCssExtractPlugin({ filename: `[name]_[contenthash:8].css` }),
new OptimizeCSSAssetsPlugin({ assetNameRegExp: /\.css$/g, cssProcessor: require('cssnano') }),
new CleanWebpackPlugin(),
new HTMLInlineCSSWebpackPlugin() ].concat(htmlWebpackPlugin)
sourceMap:
参考文档:
http://www.ruanyifeng.com/blog/2013/01/javascript_source_map.html
如何启用sourceMap?
//@ sourceMappingURL=/path/to/file.js.map
sourceMap类型是:
eval, source-map, inline-source-map
提取公共资源:
1. html-webpack-external-plugin:
new HtmlWebpackExternalsPlugin({ externals: [ { module: 'react', entry: 'https://11.url.cn/now/lib/16.2.0/react.min.js', global: 'React', }, { module: 'react-dom', entry: 'https://11.url.cn/now/lib/16.2.0/react-dom.min.js', global: 'ReactDOM', }, ], })
2. splitchunks:
(1) 将react、react-dom这种大库抽离出来,单独打包
optimization: { splitChunks: { cacheGroups: { vendors: { test: /(react|react-dom)/, name: 'vendors', chunks: 'all', } } } },
<body> <div></div> <script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react.min.js"></script> <script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react-dom.min.js"></script> </body>
(2)将公共使用的方法抽离出来common, 单独打包js
optimization: { splitChunks: { minSize: 0, cacheGroups: { commons: { name: 'commons', chunks: 'all', minChunks: 2 } } } }
tree shaking: 摇树优化:
1个模块可能有多个方法,只要其中的某个方法用到了,则整个文件都会被打包到bundle里面去,tree shaking就是只把用到的方法打入bundle, 没用到的方法会在uglify阶段被擦除掉。
使用:webpack默认支持,在.babelrc里面设置modules:false即可。
production的mode下会默认开启。
要求:必须是ES6的语法,CJS的方式不支持
DCE: dead code elimination 死代码消除
代码不会被执行
代码执行的结果不会被用到
代码只会影响死变量(只写不读)
如果不开启tree shaking的话,(设置mode为none),那么一个js中的方法只引用了,但是并没有在代码里面使用,则会在打包后的bundle包里面搜到的。开启tree shaking(设置mode为production),那么打包出来的bundle包已经将这个没有用到的方法进行擦除
Scope Hoisting 使用和原理分析:
被webpack转换后的模块会带上一层包裹
import会被转换成_webpack_require,用来加载模块,返回module.exports.
_webapack_require__(0) 执行代码块
原理:将所有的模块的代码按照引用顺序放在一个函数作用域里面,然后适当的重命名一些变量以防止变量名冲突
对比:通过scope hoisting 可以减少函数声明代码和内存开销。
默认mode为production就会自动开启scope hoisting, 执行这个插件。
plugins: [ new webpack.optimize.ModuleConcatenationPlugin() ]
必须是ES6语法,CJS不支持。
代码分割和动态import:
懒加载JS脚本:
CommonJS: require.ensure
ES6:动态 import (目前还没有原生支持,需要babel转换)
如何使用动态import?
1. 安装babel插件:
npm install @babel/plugin-syntax-dynamic-import -D
2. ES6: 动态import (目前还没有原生支持,需要babel转换)
{ 'plugins': ['@babel/plugin-syntax-dynamic-import'] ... }
import('./test.js') 返回的是一个promise
webpack和ESLint结合:
一、开发阶段增加precommit钩子:
1. 安装husky:
npm i husky -D
2.增加npm script, 通过lint-staged增量检查修改的文件
在package.json文件中添加如下:
"husky": { "hooks": { "commit-msg": "validate-commit-msg" } }, "lint-staged": { "src/**/*.ts": [ "eslint --fix", "git add" ], "src/**/*.tsx": [ "eslint --fix", "git add" ] }
二、webpack与eslint集成:
使用eslint-loader,构建时检查JS规范:
module: { rules: [ { test: /.js$/, exclude: /node_modules/, use: ['babel-loader', 'eslint-loader'] }] }