如何在preact中延迟加载组件?
How to lazy load components in preact?
我的目标是在构建时获得两个包,一个用于 index.tsx
文件,另一个用于 lazy.tsx
文件。我很确定我只是在某处遗漏了一两个选项。
GitHub MCVE - example project link
文件src/index.tsx
import { render, h } from 'preact';
let a: any = null;
let b = 0;
const App = () => (
<div>
<button
onClick={() => {
import('./lazy').then(M => {
console.log('LOADED COMPONENT');
a = <M.default />;
b++;
render(<App></App>, document.body);
});
}}
>
test
</button>
{a} {b}
</div>
);
render(<App></App>, document.body);
src/lazy.tsx
import { h, FunctionComponent } from 'preact';
console.log('LAZY');
interface LazyProps {}
const Lazy: FunctionComponent<LazyProps> = props => {
const {} = props;
return <div>LAZY LOADED COMPONENT</div>;
};
export default Lazy;
Webpack 配置
{
entry: {
index: `${__dirname}/src/index.tsx`
},
output: {
path: resolve(__dirname, 'dist'),
chunkFilename: '[name].[id].js',
filename: '[name].bundle.js'
},
plugins: [new HtmlWebpackPlugin()],
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: [/node_modules/]
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
optimization: {
minimize: false
}
}
上面的代码工作正常,没有任何错误,但是它没有像预期的那样使用 Webpack 代码拆分生成多个包。
编辑:
这是 link 到 working example project
您的配置有两个问题。
首先使用您的 TypeScript 配置:
{
"compilerOptions": {
"target": "ES5",
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"jsx": "react",
"jsxFactory": "h",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"src/**/*.tsx"
]
}
要记住的两个重要属性是:
module
: 'ESNext'
moduleResolution
: 'node'
一旦你将 module
设置为 ESNext
,你就不能在 TypeScript 中编写你的 Webpack 配置,因为它期望模块是 commonjs
。所以将其更改为 CommonJS 格式的纯 JS:
const Configuration = require('webpack').Configuration;
const Dev = require('webpack-dev-server').Configuration;
const resolve = require('path').resolve;
const HtmlWebpackPlugin = require('html-webpack-plugin');
const config = {
entry: {
index: `${__dirname}/src/index.tsx`
},
output: {
path: resolve(__dirname, 'dist'),
chunkFilename: '[name].[id].js',
filename: '[name].bundle.js'
},
plugins: [new HtmlWebpackPlugin()],
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: [/node_modules/]
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
optimization: {
minimize: false
}
};
module.exports = config;
这应该可以解决您的问题。
我的目标是在构建时获得两个包,一个用于 index.tsx
文件,另一个用于 lazy.tsx
文件。我很确定我只是在某处遗漏了一两个选项。
GitHub MCVE - example project link
文件src/index.tsx
import { render, h } from 'preact';
let a: any = null;
let b = 0;
const App = () => (
<div>
<button
onClick={() => {
import('./lazy').then(M => {
console.log('LOADED COMPONENT');
a = <M.default />;
b++;
render(<App></App>, document.body);
});
}}
>
test
</button>
{a} {b}
</div>
);
render(<App></App>, document.body);
src/lazy.tsx
import { h, FunctionComponent } from 'preact';
console.log('LAZY');
interface LazyProps {}
const Lazy: FunctionComponent<LazyProps> = props => {
const {} = props;
return <div>LAZY LOADED COMPONENT</div>;
};
export default Lazy;
Webpack 配置
{
entry: {
index: `${__dirname}/src/index.tsx`
},
output: {
path: resolve(__dirname, 'dist'),
chunkFilename: '[name].[id].js',
filename: '[name].bundle.js'
},
plugins: [new HtmlWebpackPlugin()],
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: [/node_modules/]
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
optimization: {
minimize: false
}
}
上面的代码工作正常,没有任何错误,但是它没有像预期的那样使用 Webpack 代码拆分生成多个包。
编辑: 这是 link 到 working example project
您的配置有两个问题。
首先使用您的 TypeScript 配置:
{
"compilerOptions": {
"target": "ES5",
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"jsx": "react",
"jsxFactory": "h",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"src/**/*.tsx"
]
}
要记住的两个重要属性是:
module
: 'ESNext'moduleResolution
: 'node'
一旦你将 module
设置为 ESNext
,你就不能在 TypeScript 中编写你的 Webpack 配置,因为它期望模块是 commonjs
。所以将其更改为 CommonJS 格式的纯 JS:
const Configuration = require('webpack').Configuration;
const Dev = require('webpack-dev-server').Configuration;
const resolve = require('path').resolve;
const HtmlWebpackPlugin = require('html-webpack-plugin');
const config = {
entry: {
index: `${__dirname}/src/index.tsx`
},
output: {
path: resolve(__dirname, 'dist'),
chunkFilename: '[name].[id].js',
filename: '[name].bundle.js'
},
plugins: [new HtmlWebpackPlugin()],
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: [/node_modules/]
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
optimization: {
minimize: false
}
};
module.exports = config;
这应该可以解决您的问题。