moment

First, problem location

First look at the code structure

import React from 'react'
import { render } from 'react-dom'
import moment from 'moment'

const App = () => {
  const date = new Date()
  return (
    <div>
      <h1>{date.toLocaleDateString()}</h1>
      <h1>{moment().format('YYYY-MM-DD')}</h1>
    </div>
  )
}

render(<App/>, document.getElementById('app'))
Copy the code

  • The two images above are the result of compiling without moment and using moment respectively

  • It’s only a few lines of code, and the compiled files are so different. After a bit of Internet research, it turns out that all locales are packaged, and the initial solution is webpack.ignoReplugin.

  • What does IgnorePlugin do?

Second, IgnorePlugin principle analysis

// webpack.config.js ... Plugins: [new webpack.ignoreplugin (/^\.\/locale$/, /moment$/) // configure ignore rule]Copy the code

How it works: During webpack compilation, if the imported file path matches /^\.\/locale$/, the file will be ignored and will not be packaged.

  • searchmomentThe package compiled file did not find an exact match/^\.\/locale$/The import statement of the re, onlyaliasedRequire('./locale/' + name)This statement is related to locale, but it doesn’t match the re, but it doesmomentSRC source fileimport ... from './locale'. But in themomentthepackage.json“Main” refers to the compiled file, not the SRC file.

  • Oh, my God, request in this picture is./localeBlind or webpack problem? “Moment” < span style = “box-sizing: border-box; color: RGB (51, 51, 51); line-height: 22px; font-size: 14px! Important; word-break: break-allaliasedRequire('./locale/' + name)What’s going on?

  • The original Webpack compilation, encounteredrequire('./locale/' + name)When an expression of this type, Webpack looks up the directory'./locale/'The following matches regular expressions$/ / ^. * \.The file. Since name is still unknown at compile time,Webpack introduces each file into the bundle as a module, which is why the compiled file is so large after the moment is introduced.

What if you need to set the locale after adding IgnorePlugin?

  1. After adding webpack.ignoReplugin, the file size is reduced, but in the settingmoment.locale('zh-cn')After that, the date after format is still in English and the language has not been switched over.
  2. The lack of functionality is definitely unacceptable. What do we do? How to do?
  3. A solution is also provided on the moment documentation,moment-locales-webpack-plugin
new MomentLocalesPlugin({
  localesToKeep: ['zh-cn'],})Copy the code
  1. The moment default locale isenIf you need to configure other languages, you can go throughlocalesToKeepOther unused language packages will not be packaged.

Moment locales-webpack-plugin

  1. If option is not configured, IgnorePlugin ignores all language packages (enExcept)
  2. If option is set, use the ContextReplacementPlugin to set the rules for webPack to find the specified locale at compile time.
.if (localesToKeep.length > 0) {
    var regExpPatterns = localesToKeep.map(function(localeName) {
        return localeName + '(\\.js)? ';
    });
    return new ContextReplacementPlugin(
        /moment[\/\\]locale/,
        new RegExp('(' + regExpPatterns.join('|') + '$'// configure the look-up rule for the WebPack compilation phase, i.e. specify the language pack); }else {
    returnnew IgnorePlugin(/^\.\/locale$/, /moment$/); }...Copy the code

That’s it.

The level is limited, the article has the mistake place, still hope big guy corrects.