主要技術棧
React,
React-redux,
React-router,
Typescript,
antd,
Immutable,
…
需求
因為專案是一個SPA頁面,隨著專案的不斷迭代,入口檔案逐漸增大(app.js),所以想減少入口檔案的體積。
方案
方案一:
-
webpack(require.ensure)+ react-router
因為使用require.ensure需要足夠深的檔案層級並且在對應檔案需要定義index.ts檔案作為require.ensure入口,書寫起來比較麻煩,而且相對於工作量來說也是大有增加(具體的實現方案網上也比較多),故沒有選擇。
方案二:
-
webpack(bundle-loader)+ react-router(lazyLoadComponent)
優勢:
1、不用過多的檔案層級,保持檔案的prue。
2、不用自己定義require.ensure
安裝bundle-loader
npm install bundle-loader --save-dev
webpack中載入loader(這裡使用的是webpack2)
export default {
entry: entries,
output: {
path: __dirname,
filename: `${dist}/js/[name].js`, // 這裡的dist是我定義的變數
publicPath: `https://127.0.0.1/`, // 這裡很關鍵=>單獨拿出來解釋
},
resolve: {
extensions: [
`.js`,
`.jsx`,
`.ts`,
`.tsx`,
`.css`,
`.less`,
`.json`,
`.gif`,
`.html`,
`.png`,
`.webp`,
`.jpg`,
],
},
module: {
rules: [
{
test: /.jsx?$/,
loader: `babel-loader`,
},
{
test: /.(tsx|ts)/,
exclude: [
path.resolve(__dirname, "src/pages/")
],
loader: `ts-loader`,
},
{
test: /src\pages(\.*).(tsx|ts)/,
use: [
`bundle-loader?lazy`,
`ts-loader`,
],
},
{
test: /.(less)?$/,
use: [
`style-loader`,
`css-loader`,
`less-loader`,
],
// loader: `style!css!less`
},
{
test: /.css$/,
loader: extractCSS.extract({
fallbackLoader: `style-loader`,
loader: `css-loader`,
}),
},
{
test: /.(jpg|png|gif|jpeg)?$/,
loader: `url-loader?limit=20480&name=${dist}/images/[name].[hash:8].[ext]`,
},
{
test: /.(eot|woff(2)?|ttf|svg)?(@.+)*$/,
loader: `url-loader?limit=20480&name=${dist}/other/[name].[hash:8].[ext]`,
}
],
},
plugins: [
/**
* DllReferencePlugin
*/
new DllReferencePlugin({
context: __dirname,
manifest,
}),
/**
* CommonsChunkPlugin
*/
new CommonsChunkPlugin({
name: `common`,
filename: `${dist}/common.js`,
minChunks: 2,
chunks: entriesKey
}),
],
devtool: `cheap-module-source-map`,
devServer: {
port,
https,
contentBase: ROOTPATH,
compress: true,
inline: true,
quiet: false,
stats: { colors: true },
watchOptions: {
aggregateTimeout: 300,
poll: true,
},
headers: {
`Access-Control-Allow-Origin`: `*`,
},
}
};
配置詳解
{
test: /src\pages(\.*).(tsx|ts)/,
use: [
`bundle-loader?lazy`,
`ts-loader`,
],
},
test:是我寫的正則用來匹配我需要非同步載入的檔案,並且使用use中的bundle-loader->ts-loader。
(ps:在ts-loader編譯全域性檔案時,需要exclude[需要非同步載入的路徑])
route配置
// router.tsx
import * as EffectiveCustomer from `./pages/wuyoubao/customerManagement/effectiveCustomer`;
function lazyLoadComponent(lazyModule) {
return (location, cb) => {
lazyModule(module => cb(null, module.default));
}
}
<Router history={history}>
<Route path="/admindev/basic/common" {...this.props} {...routerProps}>
<IndexRoute getComponent={lazyLoadComponent(Index)}/>
<Route path="/api/wuyoubao/effective" getComponent={lazyLoadComponent(EffectiveCustomer)}/>
</Route>
</Router>
注意事項
因為router.tsx中引用的tsx全部是被bundle-loader編譯的,而bundle-loader對ES6特性支援不是很好,比如:
-
ES6可以解析
import { OrderInfoMessage } from `./fundConfirmCom/fundConfirmInfoOrder`;
console.log(OrderInfoMessage)
// 可以解析
但是這種方式bundle-loader解析不了,它所能解析的方式:
-
bundle-loader解析module
import { OrderInfoMessage } from `./fundConfirmCom/fundConfirmInfoOrder`;
console.log(OrderInfoMessage) // undefined
// bundle-loader可以識別的方式:
import * as OrderInfoMessage from `./fundConfirmCom/fundConfirmInfoOrder`;
console.log(OrderInfoMessage) // 可以解析