webpack + react + antd + css_modules


下图是项目目录结构图,红色部分可直接忽略。

一,初始化项目

新建项目文件夹,进入目录执行命令

    npm init

可以自动创建一个package.json文件。这是一个标准的npm说明文件,里面蕴含了丰富的信息,包括当前项目的依赖模块,自定义的脚本任务等等。

二,安装webpack

//全局安装
npm install -g webpack
//安装到你的项目目录,在本项目中安装Webpack作为依赖包
npm install --save-dev webpack

三,新建模板页面和入口js文件。

在根目录下吸纳建src目录,此目录为存放源代码的目录。 进入src目录:

  1. 新建index.tmpl.html文件

     <!doctype html>
     <html lang="en">
    
     <head>
         <meta charset="UTF-8">
         <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
         <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
         <title></title>
     </head>
    
     <body>
         <div id="root"></div>
         <!-- <script type="text/javascript" src="./static/layui/layui.all.js"></script> -->
         <!-- CDN外链的js引入可以写在这里,打包时候把js的整个文件夹copy到输出目录即可 -->
     </body>
    
     </html>
    

2.新建index.js文件

import React from 'react';
import { render } from 'react-dom';
import "babel-polyfill";

class App extends React.Component {

    render() {
        return (
            <div>
                //此处可以用一级路由来分拨路由页面。 省略
            </div>
        )
    }
}

render(<App />, document.getElementById('root'))

四,正式使用webpack(一切皆模块)

webpack可以用本地开发服务器作为环境,亦可打包输出后在生产环境上执行。 因此开发环境和生产环境分开配置比较友好。

Webpack有一个不可不说的优点,它把所有的文件都都当做模块处理,JavaScript代码,CSS和fonts以及图片等等通过合适的loader都可以被处理。

webpack提供两个工具处理样式表,css-loader 和 style-loader,二者处理的任务不同,css-loader使你能够使用类似@import 和 url(...)的方法实现 require()的功能,style-loader将所有的计算后的样式加入页面中,二者组合在一起使你能够把样式表嵌入webpack打包后的JS文件中。

开发环境

进入根目录

  1. 新建webpack.config.js文件。

     const webpack = require('webpack');
     const HtmlWebpackPlugin = require('html-webpack-plugin');//第三方插件,需要安装
     const path = require('path');
     const MiniCssExtractPlugin = require("mini-css-extract-plugin");//第三方插件,需要安装
    
     module.exports = {
         devtool: 'eval-source-map',//配置source maps,四种之一
         devServer: {
             contentBase: "./dist",//本地服务器所加载的页面所在的目录
             historyApiFallback: true,//不跳转
             inline: true,//实时刷新
             hot: true
         },
         resolve: {
             alias: {
                 '@': path.resolve("src")//别名,在js文件访问src文件时候,可以直接用别名@代替
             },
             extensions: ['*', '.js', '.jsx', '.json', '.less', '.css']
         },
         module: {
             rules: [
                 {
                     test: /(\.jsx|\.js)$/,
                     use: {
                         loader: "babel-loader"
                     },
                     exclude: /node_modules/
                 },
                 {
                     test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                     loader: 'url-loader',
                     options: {
                         limit: 10000,
                         outputPath: "images"
                     }
                 },
                 {
                     test: /(\.less|\.css)$/,
                     use: [//从下往上来选择解析
                         MiniCssExtractPlugin.loader,
                         {
                             loader: 'css-loader',
                             options: {
                                 importLoaders: 1,
                                 minimize: {
                                     autoprefixer: {
                                         add: true,
                                         remove: true,
                                         browsers: ['last 2 versions'],
                                     },
                                     discardComments: {
                                         removeAll: true,
                                     },
                                     discardUnused: false,
                                     mergeIdents: false,
                                     reduceIdents: false,
                                     safe: true
                                 }
                             }
                         },
                         {
                             loader: 'less-loader',
                             options: {
                                 javascriptEnabled: true
                             }
                         }
                     ]
                 }
             ],
         },
         plugins: [
             new webpack.BannerPlugin('版权所有,翻版必究'),
             new HtmlWebpackPlugin({//此插件可以配置多入口多页面
                 template: __dirname + "/src/index.tmpl.html",//一个这个插件的实例,并传入相关的参数
                 inject: true,
                 favicon: path.resolve('favicon.ico'),
                 minify: {
                     collapseWhitespace: true,
                 }
             }),
             new webpack.HotModuleReplacementPlugin(),//热加载插件
             new webpack.optimize.OccurrenceOrderPlugin(),//为组件分配ID,通过这个插件webpack可以分析和优先考虑使用最多的模块,并为它们分配最小的ID
             new webpack.DefinePlugin({
                 'process.env': {
                     'http_env': JSON.stringify(process.env.http_env)
                 }
             }),
             new MiniCssExtractPlugin({//压缩JS代码,分离CSS和JS文件
                 filename: 'css/style.css',
                 chunkFilename: 'css/style.[contenthash:5].css'
             }),
         ],
     }
    
  2. Babel

Babel用新不用旧,可以

Babel其实是一个编译JavaScript的平台,它可以编译代码帮你达到以下目的:

  • 让你能使用最新的JavaScript代码(ES6,ES7...),而不用管新标准是否被当前使用的浏览器完全支持;
  • 让你能使用基于JavaScript进行了拓展的语言,比如React的JSX;
  • 新建.babelrc文件

       {
          "presets": [
            "es2015",
            "react",
            [
              "env",
              {
                "modules": false,
                "useBuiltIns": false,
                "uglify": true,
                "targets": {
                  "browsers": ["last 2 versions"]
                }
              }
            ]
          ],
          "plugins": [
            "transform-decorators-legacy",
            "transform-class-properties",
            "syntax-dynamic-import",
            ["transform-runtime",{"polyfill": false}],
            ["transform-object-rest-spread",{"useBuiltIns": true}],
            ["import", { "libraryName": "antd", "style": true }]
          ]
        }
    

其中transform-decorators-legacy为装饰器。

Babel其实可以完全在 webpack.config.js 中进行配置,但是考虑到babel具有非常多的配置选项,在单一的webpack.config.js文件中进行配置往往使得这个文件显得太复杂,因此一些开发者支持把babel的配置选项放在一个单独的名为 ".babelrc" 的配置文件中。

  1. 同理postcss的配置也可以单独配置,减轻webpack的压力和复杂度。

在根目录新建postcss.config.js

// postcss.config.js
module.exports = {
    plugins: [
        require('autoprefixer')
    ]
}

4.新建webpack.production.config.js文件,比webpack.config.js多了output的配置,少了本地服务器的配置,其余可以不变。

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require("clean-webpack-plugin");
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
    devtool: "null",
    entry: __dirname + "/src/index.js", //已多次提及的唯一入口文件
    output: {
        path: __dirname + "/dist", //打包后的文件存放的地方
        filename: "js/bundle.js" //打包后输出文件的文件名
    },
    resolve: {
        alias: {
            '@': path.resolve("src")
        },
        extensions: ['*', '.js', '.jsx', '.json', '.less', '.css']
    },
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            },
            {
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    outputPath: "images"
                }
            },
            {
                test: /(\.less|\.css)$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 1,
                            minimize: {
                                autoprefixer: {
                                    add: true,
                                    remove: true,
                                    browsers: ['last 2 versions'],
                                },
                                discardComments: {
                                    removeAll: true,
                                },
                                discardUnused: false,
                                mergeIdents: false,
                                reduceIdents: false,
                                safe: true
                            }
                        }
                    },
                    {
                        loader: 'less-loader',
                        options: {
                            javascriptEnabled: true
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin(['dist', 'build'], { root: __dirname, verbose: true, dry: false }),
        new webpack.BannerPlugin('版权所有,翻版必究'),
        new HtmlWebpackPlugin({//此插件可以配置多入口多页面
            template: __dirname + "/src/index.tmpl.html",//一个这个插件的实例,并传入相关的参数
            inject: true,
            favicon: path.resolve('favicon.ico'),
            minify: {
                collapseWhitespace: true,
            }
        }),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.DefinePlugin({
            'process.env': {
                'http_env': JSON.stringify(process.env.http_env)
            }
        }),
        new MiniCssExtractPlugin({
            filename: 'css/style.css',
            chunkFilename: 'css/style.[contenthash:5].css'
        }),
        new CopyWebpackPlugin([{
            from: path.join(__dirname, 'src/static'),
            to: path.join(__dirname, 'dist', 'static')
        }])
    ]
}

五,修改package.json文件的script字段

script 是指定义了npm的脚本字段

start:用以开启本地服务器 build: 执行webpack.production.config.js文件

说明:cross-env为跨平台传参 NODE_ENV 和 http_env ,NODE_ENV是要指定开发环境还是生产环境,http_env是自定义的api主机ip地址,为测试环境和生产环境区分开来。支持多生产环境。

{
  "name": "zzj-webpack-sample-project",
  "version": "1.0.0",
  "description": "这是我的第一个webpack个人搭建",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack",
    "server": "cross-env NODE_ENV=development http_env=development webpack-dev-server --open --mode development",
    "build": "cross-env NODE_ENV=production http_env=production webpack --config ./webpack.production.config.js --progress --mode production"
  },
  "main": "main.js",
  "dependencies": {
    "@antv/data-set": "^0.9.6",
    "@antv/g2": "^3.2.7",
    "antd": "^3.10.8",
    "axios": "^0.18.0",
    "babel-plugin-transform-object-assign": "^6.22.0",
    "babel-polyfill": "^6.26.0",
    "codemirror": "^5.40.0",
    "crypto-js": "^3.1.9-1",
    "extract-text-webpack-plugin": "^4.0.0-beta.0",
    "immutability-helper": "^2.8.1",
    "jquery": "^3.3.1",
    "js-cookie": "^2.2.0",
    "layui-layer": "^1.0.9",
    "mobx": "^4.1.0",
    "mobx-react": "^5.0.0",
    "object-assign": "^4.1.1",
    "postcss-flexbugs-fixes": "^4.1.0",
    "promise": "^8.0.1",
    "react": "^16.2.0",
    "react-codemirror": "^1.0.0",
    "react-codemirror2": "^5.1.0",
    "react-dnd": "^5.0.0",
    "react-dnd-html5-backend": "^5.0.1",
    "react-dom": "^16.2.0",
    "react-loadable": "^5.3.1",
    "react-router-dom": "^4.2.2",
    "viser-react": "^2.3.3",
    "webpack": "^4.26.0",
    "whatwg-fetch": "^2.0.4"
  },
  "devDependencies": {
    "autoprefixer": "^9.3.1",
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.3",
    "babel-plugin-import": "^1.6.6",
    "babel-plugin-react-transform": "^3.0.0",
    "babel-plugin-syntax-dynamic-import": "^6.18.0",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-plugin-transform-object-rest-spread": "^6.26.0",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-runtime": "^6.26.0",
    "clean-webpack-plugin": "^1.0.0",
    "compression": "^1.7.2",
    "copy-webpack-plugin": "^4.5.1",
    "cross-env": "^5.1.3",
    "css-loader": "^0.28.11",
    "express": "^4.16.2",
    "file-loader": "^1.1.11",
    "html-webpack-plugin": "^3.2.0",
    "less": "^2.7.3",
    "less-loader": "^4.1.0",
    "mini-css-extract-plugin": "^0.4.5",
    "opn": "^5.2.0",
    "ora": "^2.0.0",
    "postcss-loader": "^3.0.0",
    "rimraf": "^2.6.2",
    "style-loader": "^0.21.0",
    "url-loader": "^1.0.1",
    "webpack-cli": "^3.1.1",
    "webpack-dev-middleware": "^3.1.3",
    "webpack-dev-server": "^3.1.10",
    "webpack-hot-middleware": "^2.22.1"
  },
  "author": "Tsang",
  "license": "ISC"
}

results matching ""

    No results matching ""