Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 9 题: 简单实现项目代码按需加载,例如import { Button } from 'antd',打包的时候只打包button #9

Open
airuikun opened this issue Apr 8, 2019 · 6 comments

Comments

@airuikun
Copy link
Owner

airuikun commented Apr 8, 2019

原理很简单,就是将

import { Select, Pagination, Button } from 'xxx-ui';

通过babel转化成

import Button from `xxx-ui/src/components/ui-base/Button/Button`;
import Pagination from `xxx-ui/src/components/ui-base/Pagination/Pagination`;
import Select from `xxx-ui/src/components/ui-base/Select/Select`;

自定义拓展一个babel插件,代码如下:

visitor: {
	ImportDeclaration (path, { opts }) {
	    const specifiers = path.node.specifiers;
	    const source = path.node.source;

            // 判断传入的配置参数是否是数组形式
	    if (Array.isArray(opts)) {
	        opts.forEach(opt => {
	            assert(opt.libraryName, 'libraryName should be provided');
	        });
	        if (!opts.find(opt => opt.libraryName === source.value)) return;
	    } else {
	        assert(opts.libraryName, 'libraryName should be provided');
	        if (opts.libraryName !== source.value) return;
	    }

	    const opt = Array.isArray(opts) ? opts.find(opt => opt.libraryName === source.value) : opts;
	    opt.camel2UnderlineComponentName = typeof opt.camel2UnderlineComponentName === 'undefined'
	        ? false
	        : opt.camel2UnderlineComponentName;
	    opt.camel2DashComponentName = typeof opt.camel2DashComponentName === 'undefined'
	        ? false
	        : opt.camel2DashComponentName;

	    if (!types.isImportDefaultSpecifier(specifiers[0]) && !types.isImportNamespaceSpecifier(specifiers[0])) {
	        // 遍历specifiers生成转换后的ImportDeclaration节点数组
    		const declarations = specifiers.map((specifier) => {
	            // 转换组件名称
                    const transformedSourceName = opt.camel2UnderlineComponentName
                	? camel2Underline(specifier.imported.name)
                	: opt.camel2DashComponentName
            		    ? camel2Dash(specifier.imported.name)
            		    : specifier.imported.name;
    		    // 利用自定义的customSourceFunc生成绝对路径,然后创建新的ImportDeclaration节点
                    return types.ImportDeclaration([types.ImportDefaultSpecifier(specifier.local)],
                	types.StringLiteral(opt.customSourceFunc(transformedSourceName)));
                });
                // 将当前节点替换成新建的ImportDeclaration节点组
    		path.replaceWithMultiple(declarations);
    	}
    }
}
@David-Tsui
Copy link

請問何時會需要如此功能呢?(搔頭

@chengqilong
Copy link

請問何時會需要如此功能呢?(搔頭

看来你还不知道按需使用antd,或者其他第三方的库,这是减少包体积的常见问题呀

@David-Tsui
Copy link

David-Tsui commented Apr 15, 2019

請問何時會需要如此功能呢?(搔頭

看来你还不知道按需使用antd,或者其他第三方的库,这是减少包体积的常见问题呀

喔 現在看懂了,原本以為是要延伸或是縮小第三方庫單一組件代碼。
應該是當時眼花了哈哈

@airuikun
Copy link
Owner Author

請問何時會需要如此功能呢?(搔頭

看来你还不知道按需使用antd,或者其他第三方的库,这是减少包体积的常见问题呀

喔 現在看懂了,原本以為是要延伸或是縮小第三方庫組件代碼。
應該是當時眼花了哈哈

嗯 现在webpack的tree shaking 和antd自带的一个plugin也有按需加载 这题就考一下按需加载的实现原理 当然 我的答案是通过编写babel插件去实现按需加载 你要是有别的方法 也可以共享出来

@xinbbbb
Copy link

xinbbbb commented Oct 9, 2019

webpack4 + babel7 已经可以实现tree shaking了

@haoolii
Copy link

haoolii commented Aug 3, 2020

太苦了吧

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants