How does import “take over the screen”?
Rejection of Module Re-export.
Module redirection is a common technique. It is heavily used in the component libraries of major vendors such as Tencent, Byte, Ali and others.
E.g. bytes in the arco-design
component library: github.com/arco-design…
By exposing all components in the comonents/index.tsx
file through redirection, you can use N components with one import at the time of use.
import Modal from '@arco-design/web-react/es/Modal'
import Checkbox from '@arco-design/web-react/es/Checkbox'
import Message from '@arco-design/web-react/es/Message'
...
import { Modal, Checkbox, Message} from '@arco-design/web-react'
Re-export is generally used to collect modules of the same type, usually in a folder as a unit, such as components、routes、utils、hooks、stories
, etc. are exposed through the respective index.tsx, which can greatly simplify the import path, improve code readability, maintainability.
Re-export in several forms
1. Direct re-export
Re-export specific members directly from another module.
export { foo, bar } from './moduleA';
2. Rename and re-export (including default export)
Import members from another module, possibly rename them, and then export them again.
The default export can also be renamed and re-exported
export { foo as newFoo, bar as newBar } from './moduleA';
export { default as ModuleDDefault } from './moduleD';
3. Re-export the entire module (excluding the default export)
Re-exports all exported members of another module as a single object. (Note: the entire export will not contain the export default)
export * from './moduleA';
4. Clustering, combining import and re-export
First import the members of the module, then use them, and finally re-export them.
import { foo, bar } from './moduleA';
export { foo, bar };
Through these forms, we can flexibly organize and manage code modules. Each form has its applicable scenario, and choosing the right way can help us build a clearer and more efficient code structure.
“Never use require.context”.
require.context
is a very useful feature that allows us to dynamically import a set of modules without explicitly importing them one after the other.
Just a piece of code allows you to just add files, components, will be automatically collected and redirected.
It works extremely well in fixed scenarios such as project routing, state management, etc. (it improves efficiency and avoids, as much as possible, the need to add a configuration that requires the movement of several files)
Especially when configuring routes, generating a large number of imports (as many imports as there are pages 😅)
import A form '@/pages/A'
import B form '@/pages/B'
...
const routesContext = require.context('./routes', false, /.ts$/);
const routes = [];
routesContext.keys().forEach(modulePath => {
const route = routesContext(modulePath);
// const routeName = modulePath.replace(/^./(.*).\w+$/, '$1');
routes.push(route.default || route)
});
export default routes;
In the case of large projects with multiple routes, using require.context
can be very useful in handling route imports.
“Never import dynamically.
Dynamic import can also achieve similar functionality to require.context
, dynamically collecting modules. For more information about import
dynamic import, you can read this article “How to use Mock data in Vite5➕React➕Ts project elegantly?
“Not interested in ProvidePlugin.
webpack.ProvidePlugin
It’s a good thing, but it shouldn’t be abused.
Variables/functions/libraries or tools used in the project can be used anywhere once configured.
Trust me – after seeing this example, if you haven’t used it, you won’t be able to wait to try it out 🤗
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.ProvidePlugin({
React: 'react',
_: 'lodash',
dayjs: 'dayjs',
Utils: path.resolve(__dirname, 'src/utils.js')
})
})
]
};
Now you can use dayjs, lodash, Utils, etc. anywhere without importing it!
The webpack.ProvidePlugin is a powerful tool that helps us reduce repetitive import statements and make the code cleaner and neater. However, it will not reduce the build size as these libraries will still be included in your final packaged file. Proper use of this plugin can improve development efficiency, but it needs to be used carefully to avoid hiding dependencies that can make the code difficult to understand and maintain.
For modules or components that need to be loaded on demand, consider using the dynamic import() syntax, which gives you more control over the timing of code loading and reduces the size of the package.
Use the ProvidePlugin with caution and only configure global variables for modules that do need to be used in multiple places to avoid unnecessary code packaging.
Alternatively, in the case of the Vite
project you can use vite-plugin-inject
instead of the ProvidePlugin
function
import inject from 'vite-plugin-inject';
...
plugins: [
inject({
dayjs: 'dayjs',
}),
]
...
Remember to configure the type if TS is used:
import dayjs from 'dayjs';
declare global {
const dayjs: typeof dayjs;
}
{
"compilerOptions": {
},
"include": [ "src/**/*", "globals.d.ts" ]
}
Extensive use of Typescript import types.
In a TS project, a screen full of imports will definitely be a part of TS. However, if you configure it wisely, you can reduce the number of imports drastically.
Here is the method that I use the most in my projects: the TS namespace. With it you can both make types modular, and even more excessively, you can directly use it without importing types 😅.
Again, it blows up just like ProvidePlugin
and can just extinguish the import
import.
Example of use:
// accout.ts
declare namespace IAccount {
type IList<T = IItem> = {
count: number
list: T[]
}
interface IUser {
id: number;
name: string;
avatar: string;
}
}
const [list, setList] = useState<IAccount.IList|undefined>();
const [user, setUser] = useState<IAccount.IUser|undefined>();
Note that ⚠️eslint may need to be configured to turn on 🔛 using namespaces!
Underutilizing the bable feature.
React
It also seems to realize that something is wrong: before version 17, due to the nature of jsx
every component needs to explicitly introduce import React from 'react'
, but after that it is converted by the compiler itself without introducing React. If you are using a version of React prior to 17 you can also modify the babel to achieve this, for more details refer to the official React website, which has a very detailed description. (It also provides a script to remove the introduction automatically)
1. Set up webpack, ts aliases.
Both shorter and more semantic import paths
resolve: {
alias: {
"@src": path.resolve(__dirname, 'src/'),
"@components": path.resolve(__dirname, 'src/components/'),
"@utils": path.resolve(__dirname, 'src/utils/')
}
}
import MyComponent from '../../../../components/MyComponent';
import MyComponent from '@components/MyComponent';
2. Setting the formatting prettier.printWidth
Setting the value too small may lead to frequent line breaks, giving enough difficult to read. The value of 120 is more appropriate (depending on the actual use of the team).
{
"printWidth": 120,
...
}
3. Dynamic global loading of components by conditions
Introduce global components in the entry file, use require.ensure or import to dynamically load components based on conditions, which can be easy to maintain, reduce references, and also reduce performance overheads
Vue.component('IMessage', function (resolve) {
if (/^\/pagea|pageb/.test(location.pathname)) {
require.ensure(['./components/message/index.vue'], function() {
resolve(require('./components/message/index.vue'));
});
}
});
4. use of babel-plugin-import
babel-plugin-import
Instead of reducing the number of imports directly, you can optimize the import statement to reduce the packaging size and improve the loading performance of your project. This is a valuable optimization for projects that use large third-party libraries.
Take arco-design
as an example:
{
"plugins": [
["import", {
"libraryName": "@arco-design/web-react",
"libraryDirectory": "es",
"style": true
}, "@arco-design/web-react"]
]
}
import { Button } from '@arco-design/web-react';
import Button from '@arco-design/web-react/es/button';
import '@arco-design/web-react/es/button/style/css.js';