Skip to main content

33 posts tagged with "Frontend"

View All Tags

Package your React Component for distribution via NPM

· 2 min read

Open in Notion

1. MAKE A PACKAGE NPM PUBLISHABLE

npm init

In the package.json, make sure these fields are populated: package.json

{
"name": "myUnflappableComponent",
"version": "0.0.29",
"main": "dist/index.js",
"publishConfig": {
"access": "restricted"
},
...
}

2. DON’T BUNDLE REACT. USE THE PARENT’S REACT AND REACT-DOM.

In package.json, add React and react-dom in the project’s peerDependencies (And remove it from dependencies, but add it to devDependencies for development)

...
"peerDependencies": {
"react": ">=15.0.1",
"react-dom": ">=15.0.1"
},
"devDependencies": {
"react": ">=15.0.1",
"react-dom": ">=15.0.1"
},
...

In your webpack configuration, create a UMD bundle

...
module.exports = {
...
output: {
path: path.join(__dirname, './dist'),
filename: 'myUnflappableComponent.js',
library: libraryName,
libraryTarget: 'umd',
publicPath: '/dist/',
umdNamedDefine: true
},
plugins: {...},
module: {...},
resolve: {...},
externals: {...}
}

And super-duper important, don’t bundle React

module.exports = {
output: {...},
plugins: {...},
module: {...},
resolve: {
alias: {
'react': path.resolve(__dirname, './node_modules/react'),
'react-dom': path.resolve(__dirname, './node_modules/react-dom'),
}
},
externals: {
// Don't bundle react or react-dom
react: {
commonjs: "react",
commonjs2: "react",
amd: "React",
root: "React"
},
"react-dom": {
commonjs: "react-dom",
commonjs2: "react-dom",
amd: "ReactDOM",
root: "ReactDOM"
}
}
}

3. SET UP YOUR .NPMIGNORE FILE

If you don’t set up a .npmignore file, npm uses your .gitignore file and bad things will happen. An empty .npmignore file is allowed. This is what mine looks like:

webpack.local.config.js

webpack.production.config.js .eslintrc .gitignore

Use @semantic to release package to NPM and publish docs to gh-pages automatically

· 2 min read

Open in Notion

  1. Install requisite dependencies

    # run local scripts for executing ts file for deploying docs
    npm i -D @types/node
    npm i -D ts-node

    # semantic-release and plugin for attaching version number to package.json
    npm i -D semantic-release
    npm i -D @semantic-release/git

    # git hooks and validate commit messages
    npm i -D husky
    npm i -D @commitlint/cli
  2. Add content to package.json

    \{
    "scripts": \{
    "deploy-docs": "ts-node tools/gh-pages-publish.ts",
    "semantic-release": "semantic-release"
    \},
    "files": [
    "dist"
    ],
    // if package scoped like @bndynet/ui, by default private, so...
    "publishConfig": \{
    "access": "public"
    \},
    "husky": \{
    "hooks": \{
    "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    \}
    \}
    \}
  3. New file .releaserc (Release Configurations)

    \{
    "branch": "master",
    "prepare": [
    "@semantic-release/npm",
    \{
    "path": "@semantic-release/git",
    "assets": [
    "package.json",
    "package-lock.json"
    ],
    "message": "chore(release): $\{nextRelease.version\} by CI\n\n$\{nextRelease.notes\}"
    \}
    ],
    "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/npm",
    "@semantic-release/github",
    "@semantic-release/git"
    ]
    \}
  4. New file .travis.yml (CI configurations for publishing docs and releasing package)

    language: node_js
    cache:
    directories:
    - ~/.npm
    notifications:
    email: false
    node_js:
    - '10'
    script:
    - npm run build
    after_success:
    - if [ "$TRAVIS_BRANCH" = "master" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then npm run deploy-docs; fi
    - if [ "$TRAVIS_BRANCH" = "master" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then npm run semantic-release; fi
    branches:
    except:
    - /^v\d+\.\d+\.\d+$/
  5. New file tools/gh-pages-publish.ts (Scripts to upload docs to gh-pages branch)

    import \{ cd, exec, echo, touch \} from "shelljs";
    import \{ readFileSync \} from "fs";
    import \{ parse \} from "url";

    let repoUrl
    let pkg = JSON.parse(readFileSync("package.json"))
    if (typeof pkg.repository === "object") \{
    if (!pkg.repository.hasOwnProperty("url")) \{
    throw new Error("URL does not exist in repository section")
    \}
    repoUrl = pkg.repository.url
    \} else \{
    repoUrl = pkg.repository
    \}

    let parsedUrl = parse(repoUrl)
    let repository = (parsedUrl.host || "") + (parsedUrl.path || "")
    let ghToken = process.env.GH_TOKEN

    echo("Deploying docs!!!")
    cd("docs")
    touch(".nojekyll")
    exec("git init")
    exec("git add .")
    exec('git config user.name "Bendy Zhang"')
    exec('git config user.email "zb@bndy.net"')
    exec('git commit -m "docs(docs): update gh-pages"')
    exec(
    `git push --force --quiet "https://${ghToken}@${repository}" master:gh-pages`
    )
    echo("Docs deployed!!")
  6. Add environment variables to CI (Travis CI)

    • GH_TOKEN or GITHUB_TOKEN: your token generated in GitHub and has repo scopes
    • NPM_TOKEN: your token generated in NPM