blog
blog copied to clipboard
使用import()配合webpack动态导入模块时,如何指定chunk name?
问题:
使用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>
)
}
}
打包编译输出:
看到这个编译输出的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>
)
}
}
打包编译输出:
感觉代码有点重复,想抽象出一个函数,入参是模块路径和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- https://github.com/webpack/webpack/issues/1949
import(`../page${componentPath}`)
这种写法是支持的啊。
@mrdulin
@Pines-Cheng 我更新了最后一段的描述,之前markdown输出的代码有些问题,没有将es6的模版字符串原样输出。你说的写法是支持的,但我这里需要的是前面的注释,为了给生成的每个chunk
文件指定名称。
最后这个loader方法好像并没有奏效
@tgxhx 对的,最后这个方法可以动态传入模块路径,生成相应的chunk,但是chunk文件的名称是无法通过这种方式动态传入的。
我的描述可能不是特别清楚,或者描述的方式对别人不是那么容易懂。这里是代码,随便看看吧 https://github.com/mrdulin/react-router-v4/tree/master/src/demo-2
@mrdulin 我写了个babel插件转换可以定义chunkName,有兴趣可以看看 https://www.npmjs.com/package/babel-plugin-webpack-async-module-name
webpack issues 已经给出类似的命名方式了.
import( /* webpackChunkName: "chunk-[request][index]" */
./${relativeModulePath} )
重定义chunkname不就是为了看清楚这是那个路由或者哪个懒加载的文件么, 这个 request 能够很明确的给出路径
我觉得足够了
@mqliutie 有验证过么,很久没关注这一块了,这个issue之前看过,不知道这个特性有没有加进去
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]" */
这个可以