第一坑 Webpack
使用webpack打包为了让浏览器,打包工具amd和cmd等等风格都可以识别到我们发行的模块,我们要配置webpack为umd格式,但是请注意umd风格不支持esm方式导入,该esm导入不指使用者通过import 导入然后用webpack在打包的方式,而是说原生浏览器中声明type="module"以后在浏览器中直接导入我们的模块,这个是esm风格umd格式打包后是不支持这种导入方式的,这是个坑点请注意。
重点是webpack配置中的output选项,libraryTarget代表声明打包后的模式风格,除此之外使用umd风格
还必须配置globalObject为this,定义挂载的全局对象,默认window,umd模式设置成this。this其实是umd
实现时注入进来的对象,它在不同场景下不一样,如浏览器下就是window
output: {
filename: "[name].umd.js",
path: ph.resolve(__dirname, "dist"),
libraryTarget: 'umd2',
globalObject: 'this'
},
第二坑 Webpack+babel
我们发行的包一定是打包好的,打包过程是什么呢,我已ts代码文件举例
首先它要通过 ts-loader 完成第一次转换,这时会生成js代码,这个js代码产生的样子和ts的配置有关
第二步 js代码 放入到 babel-loader 中做语法兼容处理,polyfill导入,这时我们的包就是支持低端浏览器的了
最终 兼容处理后的js代码会被交给webpack,webpack会将里面所有的导入语法拼合,类似import这种语法,找到模块位置最拼合处理
这里的坑点在于我们打包后的umd包,里面还是会存在require等语句的,这些是必须的,为了适用于不同场景,这时我们如果将这个包在给webpack打包,webpack会认为你的这个是需要默写模块,而不是认为成umd固定语法,导致打包失败,这也是为什么我们配置webpack时要排除node_modules的一个原因,所以你要是打包后的文件再用webpack打包就会失败,这是正常现象,当我们发布到npm上后,用户一般下载后都会排除掉本地的node_modules目录,否则它用其它拓展三方模块时同样会遇到这个问题,这不是我们打包的问题,是用户配置错误。
第三坑 Webpack+babel+typescript
出了webpack有导出风格外,babel,typescript的配置也存在这样的参数,当文件经过typescript后被打包成
commonJS风格,再经历babel导入polyfill使用esNext风格,最后到手到webpack,webpack打出来的包就会出问题,导致你使用时导出的包是undefined,这是因为webpack打包时一个包里面出现了两种不同风格打的模块导入,这也许不是你写的,但却是babel+typescript干出来的缺德事情,所以呢统一风格,我的习惯是导出esNext风格交给webpack打包。
tsconfig.json
{
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
],
"compilerOptions": {
"target": "esNext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"module": "esNext", // 这里声明ts导出模块风格是esNext风格
"resolveJsonModule": false,
"allowJs": false,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"isolatedModules": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"removeComments": true,
"sourceMap": false,
"noEmit": false,
"outDir": "./dist/",
"declaration": true,
"typeRoots": [
"node_modules/@types"
]
}
}
babel.config.js
module.exports = function (api) {
api.cache(true);
const presets = [
[
"@babel/env",
{
targets: {
node: "8",
ie: "10",
edge: "17",
firefox: "60",
chrome: "67",
safari: "11.1",
},
useBuiltIns: "usage", // 这里说明polyfill按需导入
modules: false,
// 这里说明不让babel动我的模块导入语法,但是注入polyfill时候会用esNext方式注入,这是默认的
// 如果设置commonJS,会将我所有的import 转换成require() 同时polyfill注入时用的是require()帮我注入
corejs: {
"version": 3,
"proposals": true,
}
},
],
"@babel/react"
];
const plugins = [];
return {
presets,
plugins
};
};
第四坑 Webpack+react
如果你做的是react,那么你有可能掉入这个坑中,react开发第三方组件时候是必须导入的,但是打包时候是必须不能导入的,如果你导入react一起和你的组件打包了,那么恭喜你的用户导入时候就会有两份react代码,react会报错,所以我们怎么排除react不参与打包呢,参考:
webpack设置该参数,注意注意注意,区分大小写,root指的是浏览器,浏览器场景下react实际上是会暴露
出来一个React对象,而我们的三方组件是需要这个的,而其它如commonjs等下使用,导入的实际是react,
而我们依赖的也是react,所以这个大小写是严格区分开的。
externals: {
react: {
root: "React",
commonjs2: "react",
commonjs: "react",
amd: "react"
}
},
总结
说了一大堆你可能没明白我说的是什么,或者也不知道怎么配置,那么请参考:
开发普通第三方工具:https://github.com/SystemLight/hardoor/tree/develop/template/react-component
开发react第三方组件:https://github.com/SystemLight/hardoor/tree/develop/template/react-component
如果你看了半天还是满脸的问号,好吧,好吧
安装这个工具
npm i hardoor
hardoor list // 看看有哪些模板可以用
hardoor i esnext-webpack // 在当前所在的空目录下生成一个开发普通第三方工具的模板
hardoor i react-component // 在当前所在的空目录下生成一个开发react第三方组件的模板
生成项目模板以后进入到src写你的代码就可以了。
最后,代码是什么,可以吃么?
最后,发下hardoor地址,有兴趣可以点进去给个star,反正也不花钱是不。
https://github.com/SystemLight/hardoor
网友评论