webpack4引入Ant Design和Typescript(四)

原创 Lin_Grady 教程 webpack 750阅读 2018-12-26 17:53:19 举报

前言

之前一段时间工作原因把精力都放在小程序上,趁现在有点空闲时间,刚好官方文档也补充完整了,我准备重温一下 webpack 之路了,因为官方文档已经写得非常详细,我会大量引用原文描述,主要重点放在怎么从零构建 webpack4 代码上,这不是一个系统的教程,而是从零摸索一步步搭建起来的笔记,所以前期可能bug会后续发现继续修复而不是修改文章.

webpack4从零开始构建(一)
webpack4+React16项目构建(二)
webpack4功能配置划分细化(三)
webpack4引入Ant Design和Typescript(四)
webpack4 代码去重,简化信息和构建优化(五)

继续上回分解,我们之前已经实现了脚手架的雏形,这章就从开发角度搞事情了.回顾之前的示例代码难以忍受的丑,为了兼顾界面美观和开发效率,我们会引入一些UI库使用

2019/03/14上传,代码同步到引入antd webpack4_demo_antd
2019/03/15上传,代码同步到引入typescript webpack4_demo_typescript

Ant Design React

引入 antd

首先在\src\style\style.scss引入UI库样式

然后我们开始动手装饰一下界面,打开\src\page\main.jsx

执行命令查看效果

界面如下

按需加载babel-plugin-import

上面我们引入了antd的全部样式,这样会打包太多没用到的css

于是我们引入按需加载的插件使用

这个插件能对antdantd-mobile, lodash, material-ui等库做按需加载

然后我们将\src\style\style.scss里的引入样式删除

.babelrc文件修改如下

效果如下

实际上就是帮你转换成对应模块样式引入,重新执行命令

控制台报错

ERROR in ./node_modules/antd/lib/tooltip/style/index.less 1:0
Module parse failed: Unexpected character '@' (1:0)
You may need an appropriate loader to handle this file type.

@import '../../style/themes/default';@import '../../style/mixins/index';

@ ./node_modules/antd/lib/tooltip/style/index.js 5:0-23
@ ./node_modules/antd/lib/menu/style/css.js
@ ./src/page/main.jsx
@ ./src/index.js

ERROR in ./node_modules/antd/lib/style/index.less 1:0
Module parse failed: Unexpected character '@' (1:0)
You may need an appropriate loader to handle this file type.

@import './themes/default';@import './core/index';

@ ./node_modules/antd/lib/tooltip/style/index.js 3:0-33
@ ./node_modules/antd/lib/menu/style/css.js
@ ./src/page/main.jsx
@ ./src/index.js


粗略一看,antd内置使用Less预处理器,和我们配置的Scss不兼容.

引入LESS

先安装一下依赖

然后再config/rules.js新增对Less文件处理,重新执行命令,OK了

两个地方需要注意

1, 我们业务依然保持使用Scss,所以Less只限于引入库,所以我们需要限定范围减少搜索时间

2, less-loader@3+需要在选项增加对Js引入的less文件处理

Typescript

这是一个挺好的东西,后续我可能会单独写一篇,也可能不写,我们先学下怎么引入项目先.

先安装依赖

后面如果有遇到这种错误那是因为typescript版本太高的bug,可以尝试退回到3.1.6版本试试

ERROR in ./src/index.tsx
Module build failed: Error: Final loader (./node_modules/awesome-typescript-loader/dist/entry.js) didn't return a Buffer or String
at runLoaders (C:\work\project\webpack_demo\node_modules\webpack\lib\NormalModule.js:318:18)
at C:\work\project\webpack_demo\node_modules\loader-runner\lib\LoaderRunner.js:370:3
at iterateNormalLoaders (C:\work\project\webpack_demo\node_modules\loader-runner\lib\LoaderRunner.js:211:10)
at iterateNormalLoaders (C:\work\project\webpack_demo\node_modules\loader-runner\lib\LoaderRunner.js:218:10)
at C:\work\project\webpack_demo\node_modules\loader-runner\lib\LoaderRunner.js:233:3
at context.callback (C:\work\project\webpack_demo\node_modules\loader-runner\lib\LoaderRunner.js:111:13)
at process.internalTickCallback (internal/process/next_tick.js:77:7)

  • awesome-typescript-loader可以让Webpack使用TypeScript的标准配置文件 tsconfig.json编译TypeScript代码
  • source-map-loader使用TypeScript输出的sourcemap文件来告诉webpack何时生成 自己的sourcemaps

awesome-typescript-loader

官方推荐的解析库是awesome-typescript-loader,而有些人会使用ts-loader,两者都能工作,区别在于

  1. atl has first-class integration with Babel and enables caching possibilities. This can be useful for those who use Typescript with Babel. When useBabel and useCache flags are enabled, typescript's emit will be transpiled with Babel and cached. So next time if source file (+environment) has the same checksum we can totally skip typescript's and babel's transpiling. This significantly reduces build time in this scenario.
  2. atl is able to fork type-checker and emitter to a separate process, which also speeds-up some development scenarios (e.g. react with react-hot-loader) So your webpack compilation will end earlier and you can explore compiled version in your browser while your files are typechecked.

大概意思就是拥有一流的集成和缓存,可以跳过多余的构建减少时间消耗.能够新开进程去处理类型检查等操作,并行构建项目.

我们需要在根目录创建一个tsconfig.json文件

上面属性即使不解释应该也能看懂吧

source-map-loader

source-map-loader会从入口的所有js中提取出源映射,包括内联和URL链接然后传递给webpack做处理.对一些拥有自己源映射的第三方库尤为有用,因为它们可能会引起浏览器的曲解.这样做能够让webpack去维护源映射的数据连续性,方便调试.

打开config/rules.js新增处理操作

接下来我们在webpack.common.js配置一下extensions ,因为可能大部分人再引入文件时候都习惯不补上文件扩展名,这时候webpack就会按照extensions 一个个去匹配,默认 ['.wasm', '.mjs', '.js', '.json']

然后我们开始修改文件后缀,例如src\component\view1.jsx ->src\component\view1.tsx.
现在执行命令

你会惊喜地发现终端狠狠的报错

ERROR in [at-loader] ./src/component/view1.tsx:1:33
TS7016: Could not find a declaration file for module 'react'. 'C:/work/project/webpack_demo/node_modules/react/index.js' implicitly has an 'any' type.
Try npm install @types/react if it exists or add a new declaration (.d.ts) file containing declare module 'react';

ERROR in [at-loader] ./src/component/view1.tsx:6:7
TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.

ERROR in [at-loader] ./src/component/view1.tsx:6:15
TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.

ERROR in [at-loader] ./src/component/view1.tsx:7:7
TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.

ERROR in [at-loader] ./src/component/view1.tsx:7:34
TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try npm i @types/node and then add node to the types field in your tsconfig.

因为我们还要添加React和React-DOM以及它们的声明文件到package.json文件里做为依赖.

再次执行命令依然报错

ERROR in [at-loader] ./src/component/view1.tsx:1:8
TS1192: Module '"C:/work/project/webpack_demo/node_modules/@types/react/index"' has no default export.

ERROR in [at-loader] ./src/component/view1.tsx:7:34
TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try npm i @types/node and then add node to the types field in your tsconfig.

虽然不知道原因,但是已经不能直接引入React里的东西,所以我们还要改一下引入写法

后面发现原来tsconfig.json提供了一个选项,那就不用改写法了.

后面版本问题已经被废弃了,所以我们换了个属性,具体原因Deprecated 'allowSyntheticDefaultImports' for synthetic modules

你以为这样就完了吧,不!!

ERROR in [at-loader] ./src/component/view1.tsx:8:34
TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try npm i @types/node and then add node to the types field in your tsconfig.

惊喜不惊喜?意外不意外?现在连require图片资源的语法都出问题了,于是我们跟着提示继续安装依赖

再来一遍执行命令,终于可以顺利运行了,其他相关文件也全部转成tsx格式

src\component\view2.jsx ->src\component\view2.tsx

src\page\main.jsx ->src\page\main.tsx

src\index.js ->src\index.tsx

记得要把其他文件例如package.jsonconfig/webpack.common.js等文件的index引入后缀同步改一下.

到了这步你以为你成功了,结果又是一个晴天霹雳

ERROR in [at-loader] ./src/index.tsx:6:18
TS2307: Cannot find module 'PAGE/main'.

ERROR in [at-loader] ./src/page/main.tsx:4:19
TS2307: Cannot find module 'CMT/view1'.

ERROR in [at-loader] ./src/page/main.tsx:5:19
TS2307: Cannot find module 'CMT/view2'.

因为现在tsx也需要配置自己的一套解析路径,于是我们继续修改tsconfig.json

抱着屡战屡败的勇气再次执行

终于情形一片大好,顺利打包,直到你打开界面为止...

ts-import-plugin

看来是按需加载那块出了问题了.然后继续搜索资料找到typescript专用的按需加载库

跟着文档走一个个修改

tsconfig.json

config/rules.js

继续执行命令

顺利编译完成,打开页面一看,嗯,内心毫无波动~~

main.tsx?21bb:9 Uncaught ReferenceError: antd_1 is not defined
at Object.eval (main.tsx?21bb:9)
at eval (main.tsx:58)
at Object../src/page/main.tsx (main.bundle.js:3209)
at webpack_require (main.bundle.js:20)
at eval (index.tsx?22d4:6)
at Object../src/index.tsx (main.bundle.js:3197)
at
webpack_require
(main.bundle.js:20)
at main.bundle.js:84
at main.bundle.js:87

继续埋头苦干,各种调查,发现typescript.json还有一个属性配置

再来一次!!

感谢上帝!!

收尾

因为我们现在用上typescript之后,有一些东西就可以直接废弃了,例如

按需加载babel-plugin-import已经替换成ts-import-plugin

.babelrc还原回到

因为typescript本身就支持各种JavaScript版本的转换,甚至是不同的规范 ,所以我们将js和jsx的相关loader也去掉.

暂时运行起来还没问题,但是毕竟没有经过项目实战,可能有bug.

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复