mrdulin / blog

Personal Blog - 博客 | 编程技术,软件,生活

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

使用import()配合webpack动态导入模块时,如何指定chunk name?

mrdulin opened this issue · comments

问题:

使用webpack + es2015的import()语法进行code splitting时,需要指定chunk name,便于查看chunk具体是什么文件分离出的。

webpack版本: 3.10.0

webpack相关配置:

  output: {
    publicPath: '/',
    filename: 'scripts/[name].[chunkhash].js',
    chunkFilename: 'scripts/[id].[name].[chunkhash].js',
  },

先看没有指定chunk name的写法和打包编译输出:

代码片段:

class App extends React.Component {
  render() {
    return (
      <div>
        <ul>
          <li><Link to='/'>Home</Link></li>
          <li><Link to='/about'>About</Link></li>
          <li><Link to='/topics'>Topics</Link></li>
          <li><Link to='/contact'>contact</Link></li>
        </ul>
        <Switch>
          <Route exact path='/' component={Home}></Route>
          <Route path='/about' component={asyncComponent({
            loader: () => import('../about'),
            loading: Loading
          })}></Route>
          <Route path='/topics' component={asyncComponent({
            loader: () => import('../topics'),
          })}></Route>
          <Route path='/contact' component={asyncComponent({
            loader: () => import('../contact'),
            loading: Loading
          })} />
          <Route component={asyncComponent({
            loader: () => import('../NoMatch'),
          })} />
        </Switch>
      </div>
    )
  }
}

打包编译输出:

image

看到这个编译输出的chunk name,我的表情是这样的

都是模块id, 根本不知道这些chunk文件到底是哪些模块(在一般情况下,可以简单的理解为哪些页面)。
如果某个chunk文件过大,怎么知道是哪个页面呢?

所以有必要加入人类可读chunk name

解决办法:

es2015规格中的import()本身是不支持指定动态导入模块生成的chunk文件的名称的,不过,webpack 2.6.0以后,支持使用注释的方式给动态导入的模块添加chunk name。语法如下:

import(
  /* webpackChunkName: "my-chunk-name" */
  /* webpackMode: "lazy" */
  'module'
);

好了,到这里基本就清楚了。改写后的代码和打包编译输出如下:

代码片段:

class App extends React.Component {
  render() {
    return (
      <div>
        <ul>
          <li><Link to='/'>Home</Link></li>
          <li><Link to='/about'>About</Link></li>
          <li><Link to='/topics'>Topics</Link></li>
          <li><Link to='/contact'>contact</Link></li>
        </ul>
        <Switch>
          <Route exact path='/' component={Home}></Route>
          <Route path='/about' component={asyncComponent({
            loader: () => import(/* webpackChunkName: 'about' */'../about'),
            loading: Loading
          })}></Route>
          <Route path='/topics' component={asyncComponent({
            loader: () => import(/* webpackChunkName: 'topics' */'../topics')
          })}></Route>
          <Route path='/contact' component={asyncComponent({
            loader: () => import(/* webpackChunkName: 'contact' */'../contact'),
            loading: Loading
          })} />
          <Route component={asyncComponent({
            loader: () => import(/* webpackChunkName: 'NoMatch' */'../NoMatch')
          })} />
        </Switch>
      </div>
    )
  }
}

打包编译输出:

image

感觉代码有点重复,想抽象出一个函数,入参是模块路径和chunk name? 类似:

const loader = (path, name) => () => import(/* webpackChunkName: `${name}` */  `${path}`)

为了让生成的每个chunk文件都有自己指定的名称,然而import()并不支持这样的注释,那么问题就是如何使用js动态生成注释? 也就是说,${name}需要被替换成自己指定的chunk名称,如上面的contact, NoMatch等。

参考链接:

https://doc.webpack-china.org/api/module-methods/#import-
webpack/webpack#1949


Flag Counter

commented
import(`../page${componentPath}`)

这种写法是支持的啊。

@Pines-Cheng 我更新了最后一段的描述,之前markdown输出的代码有些问题,没有将es6的模版字符串原样输出。你说的写法是支持的,但我这里需要的是前面的注释,为了给生成的每个chunk文件指定名称。

commented

最后这个loader方法好像并没有奏效

@tgxhx 对的,最后这个方法可以动态传入模块路径,生成相应的chunk,但是chunk文件的名称是无法通过这种方式动态传入的。

我的描述可能不是特别清楚,或者描述的方式对别人不是那么容易懂。这里是代码,随便看看吧
https://github.com/mrdulin/react-router-v4/tree/master/src/demo-2

commented

@mrdulin 我写了个babel插件转换可以定义chunkName,有兴趣可以看看 https://www.npmjs.com/package/babel-plugin-webpack-async-module-name

dynamic import() chunk name

webpack issues 已经给出类似的命名方式了.

import( /* webpackChunkName: "chunk-[request][index]" */ ./${relativeModulePath} )

重定义chunkname不就是为了看清楚这是那个路由或者哪个懒加载的文件么, 这个 request 能够很明确的给出路径

我觉得足够了

@mqliutie 有验证过么,很久没关注这一块了,这个issue之前看过,不知道这个特性有没有加进去

commented

dynamic import() chunk name

webpack issues 已经给出类似的命名方式了.

import( /* webpackChunkName: "chunk-[request][index]" */./${relativeModulePath})

重定义chunkname不就是为了看清楚这是那个路由或者哪个懒加载的文件么, 这个 request 能够很明确的给出路径

我觉得足够了

實證過可以正確顯示 謝謝!

我遇到的问题是打包出来的文件名类似:name0.js、name1.js。改成下面的配置就可以了:
output: {
chunkFilename: '[name].js'
}

/* webpackChunkName: "[request]" */

/* webpackChunkName: ${name} */

webpack 2.7 文档没找到,找到这里来了,哈哈 👍

我遇到的问题是打包出来的文件名类似:name0.js、name1.js。改成下面的配置就可以了:
output: {
chunkFilename: '[name].js'
}

/* webpackChunkName: "[request]" */

这个可以