rollup搭建项目

内容纲要

现在的项目基本都开始用rollup搭建的,很快要放弃webpack了。

初始化

npm init

接着按照步骤填入信息,生成package.json,默认入口为main.js,暂时写成main.js,后面会修改入口文件为编译后的文件

在根目录新建src文件夹,在src文件夹下新建main.ts文件:

export function hello () { 
    console.log('hello indeex') 
}

配置rollup

安装typescriptrollup

npm i -D typescript

npm i -S rollup

配置eslint

安装eslint

npm i -D eslint

生成eslint配置文件(这个过程有点长😁):

./node_modules/.bin/eslint --init

提示需要:

Need to install the following packages:
  @eslint/create-config

确认后根据需求选择不同配置,有三中配置:

? How would you like to use ESLint? … 
  To check syntax only
  To check syntax and find problems
❯ To check syntax, find problems, and enforce code style

选择To check syntax, find problems, and enforce code style(检查语法格式、查找问题、统一代码风格),详细规则配置见eslint文档tslint文档

接着有三种不同模式:

? What type of modules does your project use? … 
❯ JavaScript modules (import/export)
  CommonJS (require/exports)
  None of these

选择JavaScript modules (import/export)

接着是库的选择:

? Which framework does your project use? … 
  React
  Vue.js
❯ None of these

根据需求选择相应库,也可以不使用库,后期再配置,比如后期配置使用svelte

接着选择编程语言:

? Does your project use TypeScript? › No / Yes

选择YesYes使用Typescript,No使用Javascript(ECMA 262即ECMAScript)

接着选择运行环境:

? Where does your code run? …  (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser
✔ Node

选择Browser。也可以选择非浏览器环境

接着选择样式:

? How would you like to define a style for your project? … 
  Use a popular style guide
❯ Answer questions about your style

选择Answer questions about your style,由于是空项目,这里会少一个检测现有项目并自动生成的选项

接着选择格式化代码方式:

? What format do you want your config file to be in? … 
❯ JavaScript
  YAML
  JSON

选择JavaScript

接着选择代码缩进方式:

? What style of indentation do you use? … 
❯ Tabs
  Spaces

选择Tabs

接着选择字符串单双引号:

? What quotes do you use for strings? … 
  Double
❯ Single

选择Single。依据团队或个人习惯选择。双引号要使用Shift+单引号 组合键,没有单引号按键方便,但双引号是很多团队的代码规范

接着是单纯的询问使用的操作系统:

? What line endings do you use? … 
❯ Unix
  Windows

选择Unix

结尾加不加英文分号:

? Do you require semicolons? › No / Yes

选择Yes

接着是单纯的询问使用的操作系统:

? What line endings do you use? … 
❯ Unix
  Windows

选择Unix。提示需要依赖:

The config that you've selected requires the following dependencies:

eslint-plugin-react@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest

接着是询问要不要安装:

? Would you like to install them now? › No / Yes

选择Yes

最后还要询问用什么安装:

? Which package manager do you want to use? … 
❯ npm
  yarn
  pnpm

哪个安装的快用哪个。

选择后会显示要安装的依赖:

Installing eslint-plugin-react@latest, @typescript-eslint/eslint-plugin@latest, @typescript-eslint/parser@latest

安装完成后,会生成配置文件.eslintrc.js,并自动开始安装相应依赖,自动安装失败,就手动安装一遍上面提示的依赖

配置忽略文件

在根目录新建.eslintignore文件:

dist/**
node_modules/**

在根目录新建.gitignore文件:

/node_modules

/dist

# production
/build

# misc
.DS_Store

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env.local
.env.*.local

# typescript
*.tsbuildinfo

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

配置babel

安装依赖:

# 删除文件依赖
npm i -D rimraf

# typescript编译依赖
npm i -D rollup-plugin-typescript2

# rollup依赖
npm i -D @rollup/plugin-node-resolve @rollup/plugin-commonjs rollup rollup-plugin-terser

# babel依赖
npm i -D @babel/core @rollup/plugin-babel @babel/preset-env @babel/plugin-transform-runtime

@rollup/plugin-commonjs依赖为了让打包后的输出文件有commonjsesm(ecmascript module)umd三种模式

修改package.json

"main": "./dist/index.js",//rollup.config.js中设置的commonjs模式打包出的文件
"module": "./dist/index.esm.js",
"umd": "./dist/index.umd.js",
"types": "./dist/types/index.d.ts",//类型声明文件入口

修改rollup.config.js文件:

/*
 * @Author: indeex
 * @Date: 2019-06-16 21:29:23
 * @Email: indeex@qq.com
 */
import path from 'path'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import rollupTypescript from 'rollup-plugin-typescript2'
import babel from '@rollup/plugin-babel'
import { DEFAULT_EXTENSIONS } from '@babel/core'
import { terser } from 'rollup-plugin-terser'
import pkg from './package.json'

const env = process.env.NODE_ENV
const name = "RollupTypescript"

const config = {
    input: path.resolve(__dirname, "src/main.ts"),
    output: [
        //commonjs
        {
            file: pkg.main,
            format: 'cjs',
        },
        //esm
        {
            file: pkg.module,
            format: 'es',
        },
        //umd
        // {
        //     file: pkg.umd,
        //     format: 'umd'
        // },
    ],
    plugins: [
        resolve(),//解析第三方依赖
        commonjs(),//识别commonj和第三方依赖
        rollupTypescript(),//rollup编译typescript
        babel({
            babelHelpers: 'runtime',//使用runtime编译库
            exclude: 'node_modules/**',
            extensions: [
                ...DEFAULT_EXTENSIONS,
                '.ts',
            ],
        }),
    ],
}

// 对生产环境进行代码压缩
if (env === 'production') {
    config.plugins.push(terser({
        compress: {
            pure_getters: true,
            unsafe: true,
            unsafe_comps: true,
            warnings: false,
        },
    }))
}

export default config

在根目录,新建tsconfig.json文件:

{ 
    "compilerOptions": 
        { 
            /* 基础选项 */ 
            "target": "esnext", /* 指定 ECMAScript 目标版本:'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 
            "module": "esnext", /* 输出的代码使用什么方式进行模块化: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 
            "lib": [ /* 指定引用的标准库 */ 
                "esnext", 
                "dom", 
                "dom.iterable", 
            ], 
            "allowJs": true,  /* 允许编译 js 文件 */ 
            "removeComments": true, /* 输出不包含注释 */ 
            /* 严格类型检查选项 */ "strict": true, /* 启用所有严格类型检查选项 */ 
            "noImplicitAny": true, /* 检查隐含 any 类型的表达式和声明 */
            "strictNullChecks": false, /* 严格空检查. */ 
            /* 额外检查 */ 
            "noUnusedLocals": true, /* 检查无用的变量. */ 
            /* Module Resolution Options */ 
            "moduleResolution": "node", /* 指定模块查找策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6) */ 
            "baseUrl": "./", /* 查找模块的基础目录 */ 
            "paths": { 
                "@/*": [ 
                    "src/*" 
                ] 
            }, /* 记录 baseUrl 的模块路径查找别名 */ "types": [], /* 类型声明文件 */ 
            "allowSyntheticDefaultImports": true,
            "jsx": "preserve"
        },
    "include": [ 
        /* 指定编译处理的文件列表 */ 
        "src/**/*",
        "src/types.ts"
    ],
    "exclude": ["node_modules", "config", "dist", "public"]
}

在根目录,新建tsconfig.types.json文件:

{ 
    // 继承 tsconfig.json 中的通用配置 
    "extends": "./tsconfig.json", 
    "compilerOptions": { 
        "declaration": true, /* 生成相应的 '.d.ts' file. */ 
        "declarationDir": "./dist/types", /* 类型声明文件输出目录 */
        "emitDeclarationOnly": true, /* 只生成声明文件,不生成 js 文件*/ 
        "rootDir": "./src", /* 指定输出文件目录(用于输出),用于控制输出目录结构 */ 
    } 
}

在根目录,新建babel.config.js文件:

module.exports = { 
    "presets": [ 
        [ 
            "@babel/preset-env", 
            { 
                /* Babel 会在 Rollup 有机会做处理之前,将我们的模块转成 CommonJS,导致 Rollup 的一些处理失败 */ 
                "modules": false 
            } 
        ] 
    ], 
    "plugins": [ 
        [ 
            // 与 babelHelpers: 'runtime' 配合使用 
            "@babel/plugin-transform-runtime" 
        ] 
    ] 
}

babel.config.js会影响整个项目中的代码,包含node_modules中的代码
babelrc 只会影响本项目中的代码,注意如果要使用.babelrc配置,请在src下创建.babelrc文件

修改package.jsonscripts字段并增加files字段:

"scripts": {
    "clean:dist": "rimraf dist",//清空dist打包目录
    "build:types": "npm run clean:dist && tsc -b ./tsconfig.types.json",//编译ts类型声明文件
    "build": "npm run build:types && rollup -c",
    "test": "node test/test.js",
    "pretest": "npm run build"//执行test命令时禁止该命令
},
"files": ["dist"],

在终端测试:

npm run build

会生成dist文件夹,文件夹内有index.js文件、index.esm.js文件、类型声明文件

test

在根目录新建test文件夹,在文件夹下新建test.js文件:

const { hello } = require('../dist/index.js')
hello()

在终端测试:

npm run test

会在终端打印hello indeex

postcss和预处理器

rollup-plugin-postcss支持SassLessStylus

# postcss
npm i -D postcss rollup-plugin-postcss

# sass
npm i -D node-sass

# or less
npm i -D less

# or stylus
npm i -D stylus

如果安装node-sass有问题,可以更换其他预处理器

修改rollup.config.js文件:

//...
import postcss from 'rollup-plugin-postcss'
import sass from 'node-sass'

//...
plugins: [
    //...
    postcss({
        modules: true,//开启css modules,.module.css .module.sss .module.scss .module.sass .module.styl .module.stylus .module.less
        extract: true,
        minimize: productEnv,
        extensions: ['css', 'scss', 'sass'],
        process: processSass,
    }),
],

css浏览器自动补全

npm i -D autoprefixer

修改rollup.config.js文件:

//...
import autoprefixer from 'autoprefixer'

//...
plugins: [
    //...
     postcss({
        //...
        plugins: [
            autoprefixer(),
        ],
    }),
],

修改package.json文件:

//...
"browserslist": [
    "defaults",
    "not ie < 8",
    "last 2 versions",
    "> 1%",
    "iOS 7",
    "last 3 iOS versions"
]

本地服务器

npm install -D rollup-plugin-serve

修改rollup.config.js文件:

//...
import serve from 'rollup-plugin-serve'

//...
plugins: [
    //...
    serve({
        open: true,
        contentBase: "public",
        host: "localhost",
        port: 9999,
    }),
],

在根目录下新建public文件夹,在此文件夹下新建index.html文件,配置页面中的logo icon

运行npm run build会启动本地服务器并打开浏览器,并看到页面

开发环境和生产环境

在根目录下新建rollup.config.dev.js文件:

import serve from 'rollup-plugin-serve'
import config from './rollup.config'

const indexPath = 'public/index.html'

config.plugins = [
    ...config.plugins,
    serve({
        host: "localhost",
        port: 9998,
        onListening: (server) => {
            const address = server.address()
            const host = address.address === '::' ? 'localhost' : address.address
            const protocol = server.https ? 'https' : 'http'
            console.log(`Server listening at ${protocol}://${host}:${address.port}`)
        }
    }),
]

module.exports = config

在根目录下新建rollup.config.prod.js文件:

import config from './rollup.config'

process.env.NODE_ENV = 'production'

config.output.sourcemap = false
config.plugins = [...config.plugins]

module.exports = config

将所有的rollup.config开头的配置移动到根目录的config文件夹下,修改rollup.config.js

//修改路径
import pkg from './../package.json'

//修改入口路径
const config = {
    input: path.resolve( path.resolve(__dirname), '..', 'src/main.ts'),
}

修改.eslintrc.js文件:

module.exports = {
    //...
    'settings': {
        'react': {
            'version': 'detect'
        }
    }
};

修改package.json文件的scripts字段:

 "scripts": {
    "dev": "npm run lint && rollup -w -c ./config/rollup.config.dev.js",
    "clean:dist": "rimraf dist",
    "build:types": "npm run clean:dist && tsc -b ./tsconfig.types.json",
    "build": "npm run build:types && npm run lint && rollup -c ./config/rollup.config.prod.js",
    "test": "node test/test.js",
    "pretest": "npm run build",
    "lint": "eslint --fix --ext .ts,.js src"
},

代码混淆

npm i -D rollup-plugin-uglify

修改rollup.config.prod.js文件:

//...
import {uglify} from 'rollup-plugin-uglify'

//...
config.plugins = [...config.plugins, uglify({sourcemap: false})]

热更新

npm i -D rollup-plugin-livereload

修改rollup.config.dev.js文件:

//...
import livereload from 'rollup-plugin-livereload'

//...
config.plugins = [
    //...
    livereload(),
]

alias别名

npm i -D @rollup/plugin-alias

修改rollup.config.js文件:

//...
import alias from '@rollup/plugin-alias'

//...
plugins: [
    //...
    alias({
        entries: [
            {
                find: "@",
                replacement: path.resolve(path.resolve(__dirname), "..", "src"),
            },
            {
                find: "src",
                replacement: path.resolve(path.resolve(__dirname), "..", "src"),
            },
        ],
        customResolver,
    }),
],

代码格式化

npm i -D prettier rollup-plugin-prettier

在根目录下新建.prettierrc.js文件:

module.exports = {
    printWidth: 100,
    singleQuote: true,
    trailingComma: 'none',
    bracketSpacing: true,
    bracketSameLine: true,
    tabWidth: 4,
    arrowParens: "always",
}

修改rollup.config.js文件:

//...
import prettier from 'rollup-plugin-prettier'
const prettierConfig = path.resolve(path.resolve(__dirname), '..', '.prettierrc.js');

//...
plugins: [
    //...
    prettier(prettierConfig),
],

polyfill

由于babel无法转换所有新语法,如Map,需要使用babel-polyfill

npm i -D core-js regenerator-runtime

修改babel.config.js文件:

module.exports = {
    "presets": [
        [
            "@babel/preset-env",
            {
                "useBuiltIns": "usage",//按需加载polyfill
                "corejs": {
                    "version": 3
                },
            }
        ]
    ],
    //...
}

如果不需要框架基本完成了,可以直接使用html和编译的js和css文件

code enjoy! 🦖🦖🦖

作者:indeex

链接:https://indeex.club

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

发表评论

您的电子邮箱地址不会被公开。