前言
-
借鉴了优秀组件的设计思路、目录结构,结合自己的开发习惯,实战了 NPM 发包流程,记录一下实战过程中踩过的坑和个人心得。
-
配置思路从极少够用到丰富生态,每一个步骤流程都可以将当前配置结果运行起来。
-
最后补充一些非组件项目的配置建议。
-
下文内容包括:
- webpack 配置
- 开发环境配置
- 区分环境配置
- 载入打包工具
- 样式 loader 配置
- 抽离样式文件
- 处理文件引用路径
- js、es 语法兼容
- react 脚手架配置
- typescript 语法依赖
- 组件测试
- npm 发布组件
创建项目
1. 目录结构
无需优先创建,我们将会按照进度步骤来创建和调整目录。
├── config # webpack 配置
│ └── webpack.common.js # 公共部分
│ └── webpack.dev.js # 开发预览环境
│ └── webpack.prod.js # 打包发布环境
├── dist # 组件打包结果目录
├── example # 示例预览目录
│ └── app.js
│ └── index.html
├── src # 组件源码目录
│ └── ts.tsx
│ └── index.js
└── .babelrc # babel 相关配置
└── .gitignore # 指定发布 git 时需要忽略的文件和文件夹
└── .npmignore # 指定发布 npm 时需要忽略的文件和文件夹
└── LICENSE # 版权许可
└── package-lock.json # 无需手动创建,npm@5 及更高版本, 会创建此文件。
└── package.json # 无需手动创建,初始化自动创建。
└── README.md # 文档
└── tsconfig.json # typescript 配置
2. 初始化
npm init -y
npm init
初始化命令,需要配置项目名称、版本号、作者信息等,直接回车采用默认配置,以后在项目 package.json 中进行修改。-y
表示使用默认配置直接初始化。
基础
1. webpack 基础配置
npm install -D webpack webpack-cli
创建以下目录结构、文件和内容:
- config/webpack.prod.js
const path = require('path')
module.exports = {
entry: {
index: path.join(__dirname, '../src/index.js'),
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, '../dist/'),
}
}
- src/index.js
export default (count = 0) => `测试: ${count}`
- package.json
{
"name": "my-compontent",
"version": "1.0.0",
"description": "",
"main": "dist/index.js", # 声明组件入口文件
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config config/webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
}
}
测试
运行以下命令,测试运行是否正常,查看结果是否正确:
~ $ npm run build
...
Asset Size Chunks Chunk Names
bundle.js 1.04 KiB 0 [emitted] app
Entrypoint app = bundle.js
[0] ./example/app.js 275 bytes {0} [built]
...
可以看到在项目根目录下生成了一个 dist 文件夹并有一个 bundle.js 文件。 在后面章节会区分开发环境和生产环境,因为开发环境只提供测试和预览功能,而生产环境需要生成引用,所以两个环境需要配置不同参数。
2. 开发环境
npm install -D webpack-dev-server
创建以下目录结构、文件和内容:
- config/webpack.dev.js
const path = require('path')
module.exports = {
entry: {
app: path.join(__dirname, '../example/app.js'),
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, '../example/') // 开发模式下不会实际生成 bundle.js 文件,会存放到内存中的。
},
devServer: {
contentBase: path.join(__dirname, '../example/'), // 本地服务加载页面所在目录
host: 'localhost', // 指定启动 ip,localhost 表示本地
port: 3000, // 端口号 3000
open: true, // 自动打开浏览器
},
}
- example/app.js
function component() {
const element = document.createElement('div')
// lodash(目前通过一个 script 引入)对于执行这一行是必需的
element.innerHTML = _.join(['Hello', 'Compontents'], ' ')
return element
}
document.body.appendChild(component())
- example/index.html
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Compontents</title>
<script src="https://unpkg.com/lodash@4.16.6"></script>
</head>
<body>
<div id="app"></div>
<script src="bundle.js"></script>
</body>
</html>
- package.json
{
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config config/webpack.prod.js",
"start": "webpack-dev-server --config config/webpack.dev.js"
},
...
}
测试
运行以下命令,测试运行是否正常,查看结果是否正确:
~ $ npm start
...
Asset Size Chunks Chunk Names
bundle.js 362 KiB app [emitted] app
Entrypoint app = bundle.js
[0] multi (webpack)-dev-server/client?http://localhost:3000 ./example/app.js 40 bytes {app} [built]
...
ℹ 「wdm」: Compiled successfully.
可以看到运行后自动打开了浏览器并访问 localhost:3000
域名。
3. 分离环境
npm install -D webpack-merge
分离生产环境和开发环境,创建一个 common(通用) 配置,使用 webpack-merge
合并配置。
创建以下目录结构、文件和内容:
- config/webpack.common.js
module.exports = {}
- config/webpack.prod.js
const path = require('path')
const { merge } = require('webpack-merge')
// const merge = require('webpack-merge') // 旧版-引用方式
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'production', // 生产模式
entry: {
index: path.join(__dirname, '../src/index.js'),
},
output: {
filename: 'index.js',
path: path.resolve(__dirname, '../dist/'),
},
})
- config/webpack.dev.js
const path = require('path')
const { merge } = require('webpack-merge')
// const merge = require('webpack-merge') // 旧版-引用方式
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'development', // 开发模式
devtool: 'inline-source-map', // 可以追踪源码中 error 的位置
...
})
- src/index.js
export default (count = 0) => `我是生产环境输出的: ${count}`
- package.json
{
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config config/webpack.prod.js",
"start": "webpack-dev-server --config config/webpack.dev.js"
},
...
}
- example/app.js
import Test from '../src' // 引入模块和测试
function component() {
...
element.innerHTML = _.join(['Hello', 'Compontents', Test(100)], ' ')
...
}
...
测试
运行以下命令,测试运行是否正常,查看结果是否正确:
~ $ npm start
...
> webpack-dev-server --config config/webpack.dev.js
ℹ 「wds」: Project is running at http://localhost:3000/
...
运行 npm start
后,浏览器访问了 localhost:3000
并且可以看到页面上增加了新内容。
~ $ npm run build
...
> webpack --config config/webpack.prod.js
...
[0] ./src/index.js 70 bytes {0} [built]
...
可以看到上面两段命令运行时会从不同的文件中读取配置,npm start
负责运行,npm run build
负责打包产出。有个问题 npm run build
运行后在 dist
文件夹中生成了 index.js
但旧的 bundle.js
依然存在,实际弃应该被清理,我们在下一节解决它。
4. 打包优化
npm install -D clean-webpack-plugin
clean-webpack-plugin
在每次构建前清理都会 /dist 文件夹,保证生成的都是用到的文件。
创建以下目录结构、文件和内容:
- config/webpack.prod.js
const path = require('path')
const { merge } = require('webpack-merge')
// const merge = require('webpack-merge') // 旧版-引用方式
const { CleanWebpackPlugin } = require('clean-webpack-plugin') // 引入清理插件
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'production',
...
plugins: [
new CleanWebpackPlugin(),
],
})
测试
运行以下命令,测试运行是否正常,查看结果是否正确:
~ $ npm run build
会发现 dist
文件夹中的 bundle.js
被清理了
依赖
1. 加载 css、sass
npm install -D style-loader css-loader sass-loader node-sass
创建以下目录结构、文件和内容:
- config/webpack.common.js
module.exports = {
module: {
rules: [{
test: /\.(sa|sc|c)ss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
mode: 'local', // 以对象方式引入,
localIdentName: 'myCompontent-[local]', // 类名前缀,创建类名时会加上前缀:myCompontent-A 、myCompontent-B ...
},
},
},
'sass-loader',
],
}],
},
}
- src/index.scss
.test {
font-size: 18px;
color: white;
background: black;
}
- src/index.js
import styles from './index.scss'
export default (count = 0) => `<div class="${styles.test}">我是生产环境输出的: ${count}</div>`
测试
运行以下命令,测试运行是否正常,查看结果是否正确:
~ $ npm start

新的问题:再次运行 npm run build
会发现,引入的样式文件被打包到 index.js
中并没有被单独分离打包,我们接下来解决这个问题。
2. 抽离样式文件
npm install -D mini-css-extract-plugin
因为生产环境和开发环境依赖关系不同,我们需要移除 webpack.common 中的配置内容,分别配置到生产环境和开发环境中。
创建以下目录结构、文件和内容:
- config/webpack.common.js
module.exports = {} // 移除内容
- config/webpack.prod.js
const path = require('path')
const { merge } = require('webpack-merge')
// const merge = require('webpack-merge') // 旧版-引用方式
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 引入 css 单独打包插件
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const common = require('./webpack.common.js')
module.exports = merge(common, {
...
module: {
rules: [{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: {
mode: 'local', // 以对象方式引入,
localIdentName: 'myCompontent-[local]', // 类名前缀,创建类名时会加上前缀:myCompontent-A 、myCompontent-B ...
},
},
},
'sass-loader',
],
}],
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin(),
],
...
})
- config/webpack.dev.js
const path = require('path')
const { merge } = require('webpack-merge')
// const merge = require('webpack-merge') // 旧版-引用方式
const common = require('./webpack.common.js')
module.exports = merge(common, {
...
module: {
rules: [{
test: /\.(sa|sc|c)ss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
mode: 'local',
localIdentName: 'myCompontent-[local]',
},
},
},
'sass-loader',
],
}],
},
...
})
测试
运行以下命令,测试运行是否正常,查看结果是否正确:
~ $ npm run build
...
[0] ./src/index.scss 704 bytes {0} [built]
[1] ./src/index.js 139 bytes {0} [built]
...
可以看到在命令窗口输出了两条文件有关的命令,会发现在 dist
文件夹中也多了一个 index.css
文件。那么还有其它的静态资源我们要怎么处理呢?比如图片字体等。
3. 处理资源引用
npm install -D file-loader
创建以下目录结构、文件和内容:
- config/webpack.common.js
module.exports = {
module: {
rules: [{
test: /\.(png|svg|jpg|gif)$/,
loader: 'file-loader',
options: {
outputPath: 'assets', // 打包后资源存放的目录
},
}, {
test: /\.(woff|woff2|eot|ttf|otf)$/,
loader: 'file-loader',
options: {
outputPath: 'assets', // 打包后资源存放的目录
},
}],
},
}
- src/index.js
找张图片放到
src
目录下 => src/icon.png
import styles from './index.scss'
import Icon from './icon.png'
export default (count = 0) => (
`
<div>
<img src="${Icon}" />
<div class="${styles.test}">我是生产环境输出的: ${count}</div>
<i class="iconfont icon-iconfontcheck"></i>
</div>
`
)
- src/index.scss
用 iconfont 做例子,很多UI库也会有自己的 Icon 组件。
- 参考 iconfont.cn 使用说明, 需要的文件分别是:
- src/iconfont.eot
- src/iconfont.svg
- src/iconfont.ttf
- src/iconfont.woff
- src/iconfont.woff2
.test {
font-size: 18px;
color: white;
background: black;
}
// 请参考 iconfont.cn 使用方法
@font-face {
font-family: "iconfont";
src: url('iconfont.eot?t=1590137292113'); /* IE9 */
src: url('iconfont.eot?t=1590137292113#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAKgAAsAAAAABlgAAAJUAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCCcApcbAE2AiQDCAsGAAQgBYRtBzcbmQXILrBt2JMiITaW4h530No6cgBCBPVjv7337gviEumeRROZRGkkEsRGJlSme6h2OJcZgQNS2c8SgS1eCpxm5ADYEwnL7ifkXg9rr74TMWXL5cZDu0/cO/0T6IPMB5TjXjTWpEldQF0cSIHugVGcSAll3DB2gUu4T6DTrBxhR209IyhWspYF4k5TBBSbi0jJ8m2hWbM3xZOGdnkoQchj+P34VhSxFI3Kajq9bZVRwxu7qM78z7jxCVECOtxAxTYkicvazLEIwbgInZlIi9C+6oM3//++W+zVIdhfZ9V2g2movCeVq77VfIHbmmgcMjfqrcS4o7Nkeexo7WomRThMSTlcT0s7TlOOZ8vnxtxZvXn/2szsjFP0EygIDCYOFWYVPYXIQA3wZ/W+cCgMwWbj5IWrZrsrwesFQ3vq50Pae/IGf0TVsy91jeUqqapqh4vxM7V06sQ/HBgUGmsdOX0htI2M8LXMpKjalslkt9HQZQdNbbvotKX9cJchVITIDmxaBAj9HlH0ekbV74NM9hMNo/7R1B8R6HQdSWd2WQ0tvpmCwEDG4jTWJMcmjofFR/VDoIybAs1qQn4MqK/FcWFeQTHfDjbQOTb4E0oRYwQT6li4DTwGpulglzo6SCxPZcytys8ndS/KkxwLxTtEAQEDZJhoGqaROGzEH83Elz4/BCjGmQS0paemOAZQPm16rFCegh5ku9Hu1XMvz/gmKIowDIERlMOCtYFZwGRyYG79LB2QMHnUESlXlXx7EOlrzFvfbH3dMehk2UrY/qrnzsslFSQDIQAA') format('woff2'),
url('iconfont.woff?t=1590137292113') format('woff'),
url('iconfont.ttf?t=1590137292113') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1590137292113#iconfont') format('svg'); /* iOS 4.1- */
}
// 因为在 css-loader 中配置了类名前缀,所以 iconfont 类名需要用 :global 函数包裹,表示不做前缀处理。
:global {
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-iconfontcheck:before {
content: "\e61b";
}
}
测试
运行以下命令,测试运行是否正常,查看结果是否正确:
~ $ npm start

再次运行 npm run build
命令,会发现 dist
文件夹中多出了 assets
文件夹,里面存着所有的静态资源。
提示:在实际开发中静态资源会以 url 地址的方式引入,你会发现引入成熟的组件并不会要求你再去引静态资源。
4. js 语法兼容
npm install -D babel-loader @babel/core @babel/preset-env core-js
npm install -D @babel/plugin-proposal-class-properties # 编译 class 类
创建以下目录结构、文件和内容:
- config/webpack.common.js
module.exports = {
module: {
rules: [{
...
}, {
test: /\.js(x?)$/,
exclude: /node_modules/,
loader: 'babel-loader'
}],
},
}
- .babelrc
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3
}
]
],
"plugins": [
"@babel/plugin-proposal-class-properties"
]
}
测试
和下节
React 脚手架
合并测试
扩展
1. React 脚手架
npm install -D @babel/preset-react react react-dom
创建以下目录结构、文件和内容:
- .babelrc
{
"presets": [
[ ... ],
"@babel/preset-react"
],
...
}
- src/index.js
import React from 'react'
import styles from './index.scss'
import Icon from './icon.png'
export default ({ count = 0 }) => (
<div>
<img src={Icon} />
<div className={styles.test}>我是生产环境输出的: {count}</div>
<i className="iconfont icon-iconfontcheck"></i>
</div>
)
example/app.js
import React from 'react'
import ReactDom from 'react-dom'
import Test from '../src'
ReactDom.render(<Test count="1000" />, document.getElementById('app'))
example/index.html
# 使用 react-dom 渲染页面,删除
# <script src="https://unpkg.com/lodash@4.16.6"></script>
测试
运行以下命令,测试运行是否正常,查看结果是否正确:
再次运行 npm start
和 npm run build
命令,运行正常无错误。
2. typescript 扩展
npm install -D typescript @babel/preset-typescript
创建以下目录结构、文件和内容:
- .babelrc
{
"presets": [
...
"@babel/preset-react",
"@babel/preset-typescript"
],
...
}
测试
和下节
react 脚手架 ts 扩展
合并测试
3. react 脚手架 ts 扩展
npm install -D @types/react @types/react-dom
创建以下目录结构、文件和内容:
- config/webpack.common.js
module.exports = {
resolve: {
// 定义 import 引用时可省略的文件后缀名
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
module: {
rules: [{
...
}, {
test: /(\.js(x?))|(\.ts(x?))$/,
exclude: /node_modules/,
loader: 'babel-loader'
}],
},
}
- tsconfig.json
- 配置说明
- baseUrl:基础路径
- esModuleInterop:允许使用
import React from
否则对于没有默认导出的模块,必须使用import * as React from
- include:设置 ts 处理的具体路径
{
"compilerOptions": {
"baseUrl": "./",
"jsx": "react",
"esModuleInterop": true
},
"include": [
"src/*",
"example/*",
]
}
- src/ts.tsx
import React from 'react'
const text: string = '测试 typescript'
export default () => <div>{text}</div>
- src/index.js
import React from 'react'
import styles from './index.scss'
import Icon from './icon.png'
import Ts from './ts'
export default ({ count = 0 }) => (
<div>
<img src={Icon} />
<div className={styles.test}>我是生产环境输出的: {count}</div>
<i className="iconfont icon-iconfontcheck"></i>
<Ts />
</div>
)
测试
运行以下命令,测试运行是否正常,查看结果是否正确:
~ $ npm start

~ $ npm run build
...
assets/2c5104bc97e257b036d264a3eb96cb9e.ttf 1.59 KiB [emitted]
assets/2d63f7f318725f04f304f5b2c3402650.png 2.54 KiB [emitted]
assets/494ab9deb2ac6a1decee40a67548b9ad.woff 1.02 KiB [emitted]
assets/a83a4d1296e90999d007661dff12e13e.eot 1.75 KiB [emitted]
assets/a83c905a2a120f6119cdf4e502d7d455.svg 1.14 KiB [emitted]
index.css 1.57 KiB 0 [emitted] index
index.js 5.36 KiB 0 [emitted] index
Entrypoint index = index.css index.js
[0] external {"root":"React","commonjs2":"react","commonjs":"react","amd":"react"} 42 bytes {0} [built]
[1] ./src/index.scss 704 bytes {0} [built]
[3] ./node_modules/css-loader/dist/cjs.js??ref--4-1!./node_modules/sass-loader/dist/cjs.js!./node_modules/mini-css-extract-plugin/dist/loader.js!./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./src/index.scss 232 bytes {0} [built]
[5] ./src/index.js + 2 modules 884 bytes {0} [built]
| ./src/index.js 633 bytes [built]
| ./src/icon.png 87 bytes [built]
| ./src/ts.tsx 154 bytes [built]
+ 3 hidden modules
Child mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/sass-loader/dist/cjs.js!src/index.scss:
Entrypoint mini-css-extract-plugin = *
[0] ./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./src/index.scss 2.76 KiB {0} [built]
[3] ./src/iconfont.eot?t=1590137292113 87 bytes {0} [built]
[4] ./src/iconfont.woff?t=1590137292113 88 bytes {0} [built]
[5] ./src/iconfont.ttf?t=1590137292113 87 bytes {0} [built]
[6] ./src/iconfont.svg?t=1590137292113 87 bytes {0} [built]
+ 2 hidden modules
...
可以看到依赖信息和资源也打包成功,惊喜!
补充
- config/webpack.prod.js
...
module.exports = merge(common, {
...
output: {
...
libraryTarget: 'umd', // 采用通用模块定义,兼容 ES6 的模块系统、CommonJS 和 AMD 模块规范
},
...
externals: {
// 定义外部依赖,将不会将 react、react-dom 打包进去
react: 'react',
'react-dom': 'react-dom',
},
})
- config/webpack.common.js
const path = require('path')
module.exports = {
resolve: {
// 定义 import 引用时可省略的文件后缀名
extensions: ['.js', '.jsx', '.ts', '.tsx'],
alias: {
// 设置路径别名,用 @ 代示部分路径。例如:import X from '@/X.js'
'@': path.join(__dirname, '../src'),
},
},
...
}
- tsconfig.json
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["src/*"] # 上文定义的路径别名 @ 需要在 tsconfig.json 中加入相应配置。
},
...
},
...
}
- package.json
{
"name": "my-compontent", # 确保包名独一无二,若有重名会报错
"version": "1.0.0", # 确保包版本未被使用
"description": "",
"main": "dist/index.js", # 参照 package.json 标准
"module": "dist/index.js", # 参照新提案允许 JavaScript 生态系统升级使用 ES2015 模块,而不会破坏向后兼容性。
...
}
- example/app.js
import React from 'react'
import ReactDom from 'react-dom'
import Test from '@'
ReactDom.render(<Test count="1000" />, document.getElementById('app'))
再次运行 npm start
和 npm run build
命令,运行正常无错误。
测试组件
运行以下命令,测试运行是否正常,查看结果是否正确:
~ $ npm run build
~ $ npm link # 提示 permission denied 错误,使用 sudo npm link 命令
...
npm WARN sass-loader@8.0.2 requires a peer of sass@^1.3.0 but none is installed. You must install peer dependencies yourself.
npm WARN sass-loader@8.0.2 requires a peer of fibers@>= 3.1.0 but none is installed. You must install peer dependencies yourself.
npm WARN my-compontent@1.0.0 No description
npm WARN my-compontent@1.0.0 No repository field.
audited 917 packages in 4.688s
found 0 vulnerabilities
...
found 0 vulnerabilities
~ $ npm link my-compontent # 把打包后的组件引入到 node_modules 中
...
~/my-compontent/node_modules/my-compontent -> ~/my-compontent -> ~/my-compontent
...
在 node_modules
中查找,可以看到引入了名为 my-compontent
的包

创建以下目录结构、文件和内容:
- example/app.js
import React from 'react'
import ReactDom from 'react-dom'
import Test from 'my-compontent' // 引用 my-compontent 组件
ReactDom.render(<Test count="1000" />, document.getElementById('app'))
测试
运行以下命令,测试运行是否正常,查看结果是否正确:
再次运行 npm start
命令,运行正常无错误。
如果 npm start
运行有错误,在上面命令操作后运行 npm i
,然后再运行一遍 npm link my-compontent
命令。
其它错误 "export 'default' (imported as 'XXX') was not found in 'XXX'
因开发和测试使用相同环境而引起的错误。可以将 npm run build
生成的 dist
文件夹修改为组件的名称,再复制到 node_modules
目录 下,来测试组件。
npm 发包
- package.json
{
...
"keywords": ['my-compontent'], # npm 上能搜索到包的关键词
"author": "白告", # 作者
"license": "ISC", # 版权许可
...
}
- .npmignore
# 指定发布 npm 时需要忽略的文件和文件夹
# npm 默认不会把 node_modules 发上去
config
example
src
.babelrc
.npmignore
.gitignore
package-lock.json
tsconfig.json
npm-debug.log*
运行以下命令,测试运行是否正常,查看结果是否正确:
~ $ npm login # 登录
~ $ npm run build
~ $ npm publish
在 npm 上查找一下刚刚我们发布的包,并用 npm i -S my-component
安装此包。
结语
以上内容就是本人发包的全过程啦,记录一下过程和想法。上面每个步骤都可测试,保证每个流程正确和方便错误排查。
如果还有什么问题和建议请留言吧!
心得
学习配置过程对 webpack 会有更好的了解,在以后项目中对 webpack 的配置也能够快速上手,例如:多页面项目、多仓库协同开发项目都需要对 webpack 进行配置。
每天都有新技术的迭代更新,我们需要探索和学习呀!
作业
node 支持读取目录文件,根据目录结构打包输出,实现组件按需加载。