内容简介:安装webpack,并新建webpack.js文件,并初始化文件配置Polyfill是一个js库,主要抚平不同浏览器之间对js实现的差异。根据浏览器不同的UA按需加载polyfill,国内浏览器支持不好。
一.基础配置
1.init项目
mkdir react-webpack-demo cd react-webpack-demo mkdir src mkdir dist npm init -y
2.安装webpack
安装webpack,并新建webpack.js文件,并初始化文件
yarn add webpack webpack-cli webpack-dev-server -D mkdir config touch config/webpack.common.js
module.exports = { entry: ['./src/index.js'],//入口 output: { //出口 path: paths.appBuild }, module: {}, //配置 loader plugins: [], //插件 };
3.安装react react-dom
yarn add react react-dom
4.配置loader
-
loaders
loader 用来解析文件转译成浏览器可以识别的文件。如.less、.jsx等这些文件浏览器是不能正常转译的,loaders的作用就是充当着'翻译'的作用。 -
babel 输入源码 => 输出编译后的代码,总共分为三个阶段:解析,转换,生成。
babel 本身不具有任何转化功能,它把转化的功能都分解到一个个 plugin 里面。因此当我们不配置任何插件时,经过 babel 的代码和输入是相同的。
插件总共分为两种:语法插件(Babel 解析(parse) 特定类型的语法,转换插件会自动启用语法插件),转换插件(例如:箭头函数 (a) => a 就会转化为 function (a) {return a}) -
预设(Presets)
preset 可以作为 Babel 插件的组合;
Preset 是逆序排列的(从后往前)
@babel/preset-react就是一个官方 Preset -
@babel/polyfill
1.babel 默认只转换 js 语法,而不转换新的 API,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转码。
2.babel-polyfill 会污染全局变量,给很多类的原型链上都作了修改,如果我们开发的也是一个类库供 其他开发者使用,这种情况就会变得非常不可控。
3.类库开发,通常我们会倾向于使用 babel-plugin-transform-runtime
4.@babel/preset-env 获取您指定的任何目标环境,,按需转码,引入相应的插件,默认使用browserslist
@babel/core-babel 核心模块 @babel/preset-env 编译ES6等 @babel/preset-react 转换JSX @babel/preset-react 转换JSX @babel/plugin-transform-runtime 避免 polyfill 污染全局变量,减小打包体积 @babel/polyfill ES6 内置方法和函数转化垫片
配置
{ test: /\.(js|jsx)$/, include: paths.appSrc, use: [ { loader: 'babel-loader', options: { presets: ['@babel/preset-react'], plugins: [ // 按需加载lodash 'lodash', // babel-plugin-import // true是less, 可以写'css' 如果不用less ['import', { libraryName: 'antd', libraryDirectory: 'es', style: 'less' }], [ '@babel/plugin-transform-runtime', { absoluteRuntime: false, corejs: false, helpers: false, regenerator: true, // generator不会污染全局的 useESModules: false, // 转换将使用无法运行的帮助程序 }, ], // '@babel/plugin-syntax-dynamic-import' ], cacheDirectory: true, cacheCompression: isEnvProduction, compact: isEnvProduction, }, }, ], }
6. 按需引入Polyfill
Polyfill是一个js库,主要抚平不同浏览器之间对js实现的差异。根据浏览器不同的UA按需加载polyfill,国内浏览器支持不好。
<script crossorigin="anonymous" src=" https://polyfill.io/v3/polyfi... ;></script>
7. CSS loader
- style-loader :以<style></style>形式在html页面中插入css代码
- css-loader :加载.css文件 ,options{Minimize:是否开启css代码压缩。modules:是否开启css-modules}
- postcss-loader :添加浏览器前缀
- less-loader less转css
可以通过匹配文件是否带module分别配置是否要开始modules
const cssRegex = /\.css$/; const cssModuleRegex = /\.module\.css$/;
module配置
modules: { mode: 'local', localIdentName: '[local]--[hash:base64:5]', context: resolve(__dirname, 'src'), hashPrefix: 'my-less-hash', },
8. 使用 source-map,对devtool进行优化
- devtool:"cheap-module-eval-source-map",// 开发环境配置
- devtool:"cheap-module-source-map", // 线上生成配置
9. 使用 WebpackDevServer
devServer: { hot: true, contentBase: paths.appBuild, host: "0.0.0.0", // 可以使用手机访问 port: 8080, historyApiFallback: true, // 该选项的作用所有的404都连接到index.html compress: true, inline: true, }
二 优化
1.文件路径优化
- extension: 指定extension之后, 引入模块的时候,可以不用扩展名
- alias: 配置别名可以加快webpack查找模块的速度
- modules:去哪些目录下寻找第三方模块
resolve: { // 引入模块的时候,可以不用扩展名 extensions: ['.js', '.json', '.jsx'], // 别名 alias: { '@assets': resolve(__dirname, '../src/assets'), '@components': resolve(__dirname, '../src/components'), '@pages': resolve(__dirname, '../src/pages'), }, // 添加一个目录到模块搜索目录 modules: [resolve(__dirname, '../src'), 'node_modules'], },
2.静态资源托管到CDN时
- filename:决定了每个输出 bundle 的名称
- path:这些 bundle 将写入到 output.path 选项指定的目录下。
- publicPath:将上面两个准备的路径字符串前面加上外部路径,比如某个CDN: http://xx.xx.com/public/ ,此时原资源位置:js/xx.xxxxx.bundle.js --> http://xx.xx.com/public/js/xx...
3.MiniCssExtractPlugin ,抽取 css 文件
css是直接打包进js里面的. 单独生成css,css可以和js并行下载,提高页面加载效率,
loader和plugins 都要配置
4.缓存
- hash(所有文件哈希值相同,只要改变内容跟之前的不一致,所有哈希值都改变,没有做到缓存意义)
- chunkhash(同一个模块,就算将js和css分离,其哈希值也是相同的,修改一处,js和css哈希值都会变,同hash,没有做到缓存意义)
- contenthash(只要文件内容不一样,产生的哈希值就不一样)
output和new MiniCssExtractPlugin() 时,配置 filename: 'static/css/[name].[contenthash:8].css',
5. 代码分割按需加载、提取公共代码
optimization
optimization: { minimize: isEnvProduction, // 找出模块的顺序,最小的初始包,product 默认开启 occurrenceOrder: true, // runtimeChunk:会为每个仅含有 runtime 的入口起点添加一个额外 chunk; // 值 "single" 会创建一个在所有生成 chunk 之间共享的运行时文件。此设置是如下设置的别名: runtimeChunk: { name: 'manifest' }, // usedExports 不导出未使用的代码 usedExports: true, concatenateModules: true, splitChunks: { // chunks: 'async', // 必须三选一: "initial" | "all"(推荐) | "async" (默认就是async) minSize: 30000, // 最小尺寸,默认值是30kb minChunks: 1, // 最小 chunk ,默认1 maxAsyncRequests: 5, // 最大异步请求数, 默认5 maxInitialRequests: 3, // 最大初始化请求数,默认3 automaticNameDelimiter: '-', // 打包分隔符 name: true, // 打包后的名称,此选项可接收 function //设置缓存组,用来抽取满足不同规则的chunk cacheGroups: { // 这里开始设置缓存的 chunks vendor: { // key 为entry中定义的 入口名称 test: /[\\/]node_modules[\\/]/, // 正则规则验证,如果符合就提取 chunk chunks: 'initial', name: 'vendor', // 要缓存的 分隔出来的 chunk 名称 priority: 10, enforce: true, }, lazy: { test: ({ resource }) => { return /antd/.test(resource); }, chunks: 'async', name: 'lazy', priority: 10, enforce: true, }, commons: { chunks: 'all', test: ({ resource }) => { return /[\\/]node_modules[\\/]/.test(resource) && !shouldExcludeFromCommon.test(resource); }, name: 'common', minChunks: 2, maxInitialRequests: 5, minSize: 0, priority: 20, }, }, }, },
6. 文件压缩
webpack4只要在生产模式下, 代码就会自动压缩
7. 暴露全局变量
new webpack.ProvidePlugin({ fetch: 'imports-loader?this=>global!exports-loader?global.fetch!whatwg-fetch', }),
8. 指定环境,定义环境变量
DefinePlugin 允许创建一个在编译时可以配置的全局常量,这些值会被内联进那些允许传一个代码压缩参数的代码中,从而减少冗余的条件判断
new webpack.DefinePlugin({ PRODUCTION: JSON.stringify(true), VERSION: JSON.stringify("5fa3b9"), BROWSER_SUPPORTS_HTML5: true, TWO: "1+1", "typeof window": JSON.stringify("object") })
9. css tree sharking
npm i glob-all purify-css purifycss-webpack --save-dev const PurifyCSS = require('purifycss-webpack') const glob = require('glob-all') plugins:[ // 清除无用 css new PurifyCSS({ paths: glob.sync([ // 要做 CSS Tree Shaking 的路径文件 path.resolve(__dirname, './src/*.html'), // 请注意,我们同样需要对 html 文件进行 tree shaking path.resolve(__dirname, './src/*.js') ]) }) ]
10. js Tree Shaking
清除到代码中无用的js代码,只支持import方式引入,不支持commonjs的方式引入
只要mode是production就会生效,develpoment的tree shaking是不生效的,因为webpack为了方便你的调试
optimization: {
usedExports:true,
}
10. 注意点
- rule配置顺序影响构建,无用的rule全部去掉。
- loader 加载顺序:从右向左:Webpack选择了compose方式
11. 页面缓存
缓存一次后 服务器挂了 还可以用
// // 预缓存
new GenerateSW({
clientsClaim: true, skipWaiting: true, importWorkboxFrom: 'local', include: [/\.js$/, /\.css$/, /\.html$/, /\.jpg/, /\.jpeg/, /\.svg/, /\.webp/, /\.png/],
}),
12. webpack-merge
提取公共配置
module.exports = merge(common, webpackConfig);
13. 使用HappyPack
MacBook Pro 2017上测试了几把 ,并没有提升速度,反而慢了,后续再看。
三 常见问题
1. antd 打包后icons dist文件很大
resolve: {
alias: { '@ant-design/icons/lib/dist$': resolve(__dirname, '../src/assets/icons.js') },
}
并在icons.js 配置
2. antd 按需引入 配置less是报错
- 按需引入antd配置:在babel-loader plugins中添加 如下配置
- 需要先安装 babel-plugin-import
- 导入js和css模块(LESS/Sass源文件): style: true
-
导入js和css模块(css 内置文件) style:"css"
['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }],
如果是less 会报错:需要在less-loader option 里面添加javascriptEnabled: true,
如果添加自定义主题: 添加 modifyVars:
{
'primary-color': '#1DA57A', 'link-color': '#1DA57A', 'border-radius-base': '2px',
},
3. antd 需要自行引入moment
在index.html文件引入
4. css module
module: { rules: [ { test: /\.css$/i, loader: 'css-loader', options: { modules: { mode: 'local', localIdentName: '[path][name]__[local]--[hash:base64:5]', context: path.resolve(__dirname, 'src'), hashPrefix: 'my-custom-hash', }, }, }, ], },
5.UglifyjsWebpackPlugin不支持ES6语法
使用terser-webpack-plugin
以上所述就是小编给大家介绍的《webpack从零开始》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
UNIX 时间戳转换
UNIX 时间戳转换
RGB CMYK 转换工具
RGB CMYK 互转工具