记一次脚手架搭建过程(二)

现在,命令行工具搭建好了,那么接下来的任务就是搞一个项目模板,奥力给!

项目模板

​ 由于我们要做的项目模板是一个单页面应用,所以首先要借助webapackwebpack-cli来帮我们构架项目。所谓单页面应用,可以理解为只有一个html文件

第一步:创建文件夹,并初始化pakage.json文件

$ mkdir zaoren-demo && cd zaoren-demo

$ npm init -y

接着,构建如下目录结构

zaoren-demo
  |- package.json
  |- /src
    |- index.js
	|- index.html

index.js

function component() {
  var element = document.createElement('div');

  element.innerHTML = 'Hello World';

  return element;
}

document.body.appendChild(component());

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>zaoren-demo</title>
    <div id="root"></div>
</head>

<body>

</body>

</html>

第二步,安装HTMLWebpackPlugin插件,创建webpack配置文件

$ npm install html-webpack-plugin --save-dev

创建build目录,新建webpack.config.js(之后将区分dev和prod环境)

webpack.config.js

const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: '[name]-[hash:8].js',
        path: path.resolve(__dirname, '../dist')
    },
    mode: 'development',
    plugins: [
        new HTMLWebpackPlugin({
            // 用于生成的HTML文档的标题
            title: 'Webpack 开发环境配置',
            // webpack 生成模板的路径
            template: './src/index.html'
        })
    ]
}

package.json

在package.json的scripts中新增build命令找到webpack的配置文件

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config build/webpack.config.js"
},

执行 npm run build 可以看到在dist文件夹中生成了html和js文件,打开html看到 ‘Hello World’

在这里插入图片描述

这样,一个最基本的webpack程序就跑通了,也许你会觉得奇怪,为什么不和以前一样直接在html中引入js文件了呢?而是费劲去安装一个插件自动引入? 因为我们的单页面应用程序,之后会将所有的.vue,.jsx等其他格式的文件解析成浏览器能识别的js文件,从文件个数来说是不确定的,html页面依赖的js文件有可能是一个有可能是多个,从文件的名称来说,我们的文件通过hash值来命名(为了做缓存)是不确定的,所以不可能手动去引入js。

第三步,区分prod和dev环境

我们项目开发完之后,是需要打包上线的,而我们在开发阶段和打包上线阶段使用的一些插件是有区别的,所以需要我们将webpack的配置文件分成两个,修改build文件夹如下

zaoren-demo
  |- /build
    |- webpack.base.config.js
	|- webpack.dev.config.js
	|- webpack.prod.config.js

webpack.base.config.js

将webpack.config.js更名为wepack.base.config.js,相当于是dev,prod的基础配置,dev和prod环境的webpack配置文件将在此基础上拓展。

webpack.dev.config.js

const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.config.js');
// 重新封装resolve,定位到项目的根目录
const resolve = (dir) => path.join(__dirname, '..', dir);

module.exports = merge(baseWebpackConfig, {
  devtool: 'eval-source-map',
  mode: 'development',
});


webpack.prod.config.js

const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.config.js');

module.exports = merge(baseWebpackConfig, {
  mode: 'production',
});


package.json

对应的,需要在package.json中区分一下运行dev和prod环境的命令,我们先再完善一下webpack的配置再来修改package.json

第四步:拓展webpack.base.config.js

1.使用clean-webpack-plugin插件

当你多次build之后会发现,dist文件夹中将每一次的打包结果都保存下来了,clean-wepack-plugin就是用来保存最后一次生成结果的插件

安装插件:

$ npm install clean-webpack-plugin --save-dev

...
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    ...
    plugins: [
        ...,
        // 用法:new CleanWebpackPlugin(paths [, {options}])
        new CleanWebpackPlugin()
    ]
}

2.为项目添加模块解析规则

都说webpack的作用是将浏览器不能识别的文件如:less,sass,vue,jsx解析成浏览器能解析的css,js,html,所以就需要配置很多的loader去帮助我们解析各种文件(modules和plugins同级)。

安装loader

$ npm install clean-webpack-plugin --save-dev
...
module.exports = {
    ...
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            {
              loader: 'style-loader',
            },
            {
              loader: 'css-loader',
              options: {
                // 开启 sourceMop
                sourceMap: true,
              },
            },
          ],
        },
        {
          test: /\.less$/,
          use: [
            {
              loader: 'style-loader',
            },
            {
              loader: 'css-loader', // translates CSS into CommonJS
            },
            {
              loader: 'less-loader', // compiles Less to CSS
            },
          ],
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: [
            'file-loader',
          ],
        },
      ],
    },
}


下面,尝试着在src目录下新建index.less文件,并且在index.js中导入, 运行npm run build

index.js

import './index.less'
function component() {
  var element = document.createElement('div');

  element.innerHTML = 'Hello World';

  return element;
}

document.body.appendChild(component());

3.安装react和react-dom

$ npm install react react-dom --save-dev

我们修改我们的index.js代码,尝试着用jsx语法来写我们的项目

import React from "react";
import ReactDom from "react-dom";

var a = 1;
var b = 2;
c = a + b;
ReactDom.render(
    <h1>hello,word!</h1>,
    document.getElementById('root')
);

npm run build 发现报错了, 因为webpack只识别JavaScript文件,而且只能编译es5版本的JavaScript语法。实际上,我们使用ES2015,以及jsx的语法糖,webpack它根本不认识啊。怎么办?webpack 可以使用 loader 来预处理文件。 所以我们需要使用Babel转译为ES5。

4.babel的配置

安装依赖,并且在项目根目录新建.babelrc

$npm install @babel/core babel-loader @babel/preset-env @babel/preset-react --save-dev

.babelrc

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ],
  "plugins": [],
}

webpack.base.config.js中的rules增加babel-loader

...
module.exports = {
    ...
    module: {
      rules: [
        {
          test: /\.js/,
          include: path.resolve(__dirname, '../src'),
          use: ['babel-loader'],
        },
        ...
      ],
    },
}

再次执行npm run build,打包成功,打开html页面,显示hello world,至此,react和 ES2015+ 开发环境已经搭建完成了!接下来要做的事情就搭建更完善的开发环境了。

第五步:拓展webpack.dev.config.js

之前我们说过,我们使用webpack的时候,专门对dev和prod环境做了区分,那么需要我们在pakage.json中用不同的scripts来运行我们的代码

pakage.json

"build": "webpack --config build/webpack.prod.conf.js --mode=production",
"dev": "webpack --open --config build/webpack.dev.conf.js --mode=development"

使用 webpack-merge插件将webpack.base.config.js的配置合并到dev

$npm install webpack-merge  --save-dev

使用 HotModuleReplacementPlugin ,FriendlyErrorsWebpackPlugin 插件

安装依赖(HotModuleReplacementPlugin不需要安装,webpack内置的)

$npm install FriendlyErrorsWebpackPlugin  --save-dev

HotModuleReplacementPlugin 插件帮助我们在开发过程中实现热更新,修改代码后不需要手动去刷新页面。

FriendlyErrorsWebpackPlugin 插件 能够更好在终端看到webapck运行的警告和错误

webpack.dev.config.js文件内容

const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const baseWebpackConfig = require('./webpack.base.config.js');

// 重新封装resolve,定位到项目的根目录
const resolve = (dir) => path.join(__dirname, '..', dir);

// 使用merge将原来webpack.base.config.js中的配置读取到
module.exports = merge(baseWebpackConfig, {
  mode: 'development',
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new FriendlyErrorsWebpackPlugin(),
  ],
});

启用调试工具 Source Map

由于我们使用了webpack打包之后,生成的文件只有html和main.js,代码出问题的时候,很难进行调试,所以,我们需要启用调试工具Source Map

在webpack.dev.config.js 中添加devtool属性

...
module.exports = {
    mode: 'development',
+   devtool: 'eval-source-map',
    ...
}

在这里插入图片描述
这样就可以在google的调试中ctrl+p然后搜索相应的文件名,去调试我们的代码啦!

使用 webpack-dev-server 插件

不得不说,这是一个很强大的插件。能帮助我们:1.在本地启动一个服务 2.项目实现热更新 3.集成了 http-proxy-middleware 中间件做本地代理,解决开发阶段跨域问题

安装插件:

$ npm install --save-dev webpack-dev-server

webpack.dev.config.js中添加devserver配置(和devtool同级)

devServer: {
    // 必须配置的选项,服务启动的目录,默认为根目录
    contentBase: './dist',
    // 使用热加时需要设为true
    hot: true,
    inline: true,
    host: 'localhost',
    port: 8000,
    historyApiFallback: {
      disableDotRule: true,
    },
    // 出现错误时是否在浏览器上出现遮罩层提示
    overlay: true,
    stats: 'errors-only',
    // 设置接口请求代理,更多 proxy 配置请参考 https://github.com/chimurai/http-proxy-middleware#options
    proxy: {},
  },

现在,我们需要使用webpack-dev-server 来启动我们的项目,在pakage.json中修改我们的启动命令

"dev": "webpack-dev-server --open --config build/webpack.dev.config.js --mode=development"

运行 npm run dev,会发现,我们在本地的8000端口,启了一个服务来运行我们的项目,修改’hello world’为’hello world1’之后,页面自动会刷新!!!那么webpack-dev-server就集成好了(devserver中的proxy的属性非常重要,能帮助我们在开发阶段解决跨域问题,之后会说到)

第六步:集成Eslint来规范代码

当我们一个项目由多个人开发的时候,代码风格,书写规范就显得尤其重要。Eslint就是来帮助我们规范代码,并且能帮助我们避免低级错误,自动格式化代码。

1.安装eslint-loader

npm install --save-dev eslint-loader

2.安装eslint

npm install --save-dev eslint

3.在webpack.base.config.js中添加eslint-loader

在原来的babel-loader后加上一个eslint-loader

{
  test: /\.js/,
  include: path.resolve(__dirname, '../src'),
  use: ['babel-loader', 'eslint-loader'],
},

4.安装babel-eslint

npm install babel-eslint --save-dev

5.在项目根目录新建.eslintrc.js文件

我们这里借用Airbnb的校验规则,所以需要安装一些依赖

  • eslint-plugin-jsx-a11y
  • eslint-plugin-react
  • eslint-plugin-import
  • eslint-plugin-react-hooks

由于这些依赖的对版本号有一定的要求,所以我们使用eslint --init 来帮我们创建Airbnb的规则,自动帮我们下载正确的依赖版本

eslint --init

在这里插入图片描述
.eslintrc.js

const path = require('path');
const resolve = (dir) => path.resolve(__dirname, dir);

module.exports = {
  env: {
    "browser": true,
    "es6": true,
    "node": true
  },
  parser: 'babel-eslint',
  extends: [require.resolve('eslint-config-airbnb')],
  plugins: ['react', 'jsx-a11y', 'import', 'react-hooks'],
  parserOptions: {
    ecmaFeatures: {
      legacyDecorators: true,
    },
  },
  settings: {
    'import/resolver': {
      webpack: {
        node: {
          extensions: ['.js', '.jsx', '.ts', '.tsx'],
        },
        config: {
          resolve: {
            alias: {
              '@': resolve('src')
            },
          },
          extensions: ['.js', '.jsx', '.ts', '.tsx'],
        },
      },
    },
  },
  globals: {
    window: true,
    document: true,
    XMLHttpRequest: true,
    fetch: true,
    AMap: true,
    ENV: true,
  },
  rules: {
    'max-len': ['warn', { code: 120 }],
    // "no-nested-ternary": 'warn',
    'react/prefer-stateless-function': 'off', // 只有render
    'react/jsx-filename-extension': 'off', // .jsx
    'react/jsx-first-prop-new-line': 'off', // 换行
    'react/sort-comp': 'off',
    'react/jsx-closing-tag-location': 'off',
    'react/no-did-mount-set-state': 'off', // DidMount中可以使用setState
    'import/extensions': 'off', // 扩展名
    'import/prefer-default-export': 'off',
    'jsx-a11y/no-static-element-interactions': 'off',
    'jsx-a11y/click-events-have-key-events': 'off',
    // warn
    'no-plusplus': ['warn', { allowForLoopAfterthoughts: true }],
    'class-methods-use-this': 'off',
    'consistent-return': 'off',
    'no-unused-expressions': 'off',
    'no-param-reassign': 'off',
    'no-mixed-operators': 'off',
    'no-shadow': 'off',
    'react/prop-types': 'off',
    'react/forbid-prop-types': 'off',
    'react/no-array-index-key': 'off',
    'react/no-string-refs': 'off',
    'jsx-a11y/anchor-has-content': 'off',
    'jsx-a11y/anchor-is-valid': 'off',
    'jsx-a11y/no-noninteractive-element-interactions': 'off',
    'react/destructuring-assignment': 'off',
    'react-hooks/rules-of-hooks': 'warn',
    'react-hooks/exhaustive-deps': 'warn',
    'react/jsx-props-no-spreading': 'off',
    'react/jsx-one-expression-per-line': 'off',
    '@typescript-eslint/explicit-member-accessibility': 'off',
    'no-unused-vars': 'warn',
    "linebreak-style": 'off', 
    "no-console": "off",
  },
};


6.vscode的Extensions中安装Eslint插件,并且开启autoFix

在这里插入图片描述

文件 -> 首选项 -> 设置 搜索 eslint,开启autofix
在这里插入图片描述
打开我们的index.js,Ctrl+S保存时自动将我们var声明的变量 改成了const
在这里插入图片描述

小结

​ 1.完成了命令行工具的搭建,并且发布到npm官网

​ 2.搭建项目模板,区分dev和prod环境,集成开发阶段的插件

​ 3.接下来将完善webpack.prod.config.js的配置,来帮助我们的项目打包上线。

完整配置文件参考 https://github.com/zaoren/shuju-zaoren-cli/tree/Tag1.0.0/config

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值