从零搭建webpack4+react+typescript+eslint脚手架(三)

处理静态资源

js的打包基本处理完了,还有图片、音频等静态资源需要处理。

依然先装依赖:

$ npm i -D url-loader file-loader
$ npm i -D @svgr/webpack # 顺带支持一下导入svg图片

增加webpack配置:

// webpack.base.js
{
  test: /\.svg$/,
  use: ['@svgr/webpack']
},
{
  test: /\.(jpg|jpeg|bmp|png|webp|gif)$/,
  loader: 'url-loader',
  options: {
    limit: 8 * 1024, // 小于这个大小的图片,会自动base64编码后插入到代码中
    name: 'img/[name].[hash:8].[ext]',
    outputPath: config.assetsDirectory,
    publicPath: config.assetsRoot
  }
},
// 下面这个配置必须放在最后
{
  exclude: [/\.(js|mjs|ts|tsx|less|css|jsx)$/, /\.html$/, /\.json$/],
  loader: 'file-loader',
  options: {
    name: 'media/[path][name].[hash:8].[ext]',
    outputPath: config.assetsDirectory,
    publicPath: config.assetsRoot
  }
}

tips: 生产环境需要合理使用缓存,需要拷贝一份同样的配置在webpack.prod.js中,并将name中的hash改为contenthash

接下来我们要把public目录里除了index.html以外的文件都拷贝一份到打包目录中:

安装依赖:

$ npm i -D copy-webpack-plugin

增加配置:

// webpack.base.js
const CopyWebpackPlugin = require('copy-webpack-plugin');

plugins: [
  // ...other plugins
  new CopyWebpackPlugin([
    {
      from: 'public',
      ignore: ['index.html']
    }
  ])
]

提取公共模块,拆分代码

有些模块是公共的,如果不把他拆分出来,那么他会在每一个被引入的模块中出现,我们需要优化与此相关的配置。

// webpack.prod.js
entry: {
  app: './src/index.tsx',
  vendor: ['react', 'react-dom'] // 不变的代码分包
},
optimization: {
  splitChunks: {
    chunks: 'all',
    minChunks: 2,
    maxInitialRequests: 5,
    cacheGroups: {
      // 提取公共模块
      commons: {
        chunks: 'all',
        test: /[\\/]node_modules[\\/]/,
        minChunks: 2,
        maxInitialRequests: 5,
        minSize: 0,
        name: 'common'
      }
    }
  }
}

压缩代码(2019/9/18更新)

通过使用打包分析工具,我们会发现打出来的包都很大,远不能满足生产环境的体积要求,因此还需要对代码进行压缩。

安装依赖:

$ npm i -D uglifyjs-webpack-plugin mini-css-extract-plugin compression-webpack-plugin

增加和修改配置:

// webpack.prod.js
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CompressionWebpackPlugin = require('compression-webpack-plugin');

{
  test: /\.(less|css)$/,
  use: [
    MiniCssExtractPlugin.loader, // 注意书写的顺序
    {
      loader: 'css-loader',
    },
    'postcss-loader',
    {
      loader: 'less-loader',
      options: {
        javascriptEnabled: true,
      }
    }
  ]
},
// ...configs
plugins: [
  new HtmlWebpackPlugin({
    template: config.indexPath,
    minify: {
      removeComments: true,
      collapseWhitespace: true,
      removeRedundantAttributes: true,
      useShortDoctype: true,
      removeOptionalTags: false,
      removeEmptyAttributes: true,
      removeStyleLinkTypeAttributes: true,
      removeScriptTypeAttributes: true,
      removeStyleLinkTypeAttributes: true,
      removeAttributeQuotes: true,
      removeCommentsFromCDATA: true,
      keepClosingSlash: true,
      minifyJS: true,
      minifyCSS: true,
      minifyURLs: true,
    }
  }),
  new MiniCssExtractPlugin({
    filename: 'css/[name].[contenthash:8].css'
    // chunkFilename: '[name].[contenthash:8].chunk.css'
  }),
  // gzip压缩
  new CompressionWebpackPlugin({
    filename: '[path].gz[query]',
    algorithm: 'gzip',
    test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
    threshold: 10240, // 大于这个大小的文件才会被压缩
    minRatio: 0.8
  }),
],
optimization: {
  minimizer: [
    new UglifyjsWebpackPlugin({
      sourceMap: config.productionJsSourceMap
    })
  ]
}

运行打包命令,查看打包好的文件,可以看到代码都被压缩好了。

使用terser

由于uglify-es已经停止维护,所以改用目前比较流行的terser来压缩js代码。我们仅需做几处简单的修改。

首先安装依赖:

$ npm i -D terser-webpack-plugin

然后改写webpack.prod.js即可:

// const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

optimization: {
  minimizer: [
    // new UglifyjsWebpackPlugin({
    //   sourceMap: config.productionJsSourceMap
    // })
    new TerserPlugin({
      sourceMap: config.productionJsSourceMap
    })
  ]
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容