Webpack3 基本环境配置篇 | React + Webpack3 后台管理项目搭建(1)

React + Webpack3 后台管理项目搭建(1)| webpack3 配置篇

这一年的前端开发实践中,接触最多就是React后台管理的开发项目,多次对公司React项目配置进行优化升级,下面介绍的是基本的React + React-router4 + Webpack3 + less + Antd单页面应用程序的项目搭建方法。


目录

React + Webpack3 后台管理项目搭建(1)| webpack3 配置篇

一、主要npm包的版本号

二、项目结构介绍

三、package.json配置

(1)基本环境配置

(2)淘宝 NPM 镜像:

(2)配置webpack打包命令:

四、Webpack3配置方法介绍

(1)“build”- 产品级编译方法:

(2)“watch-dev”- 前端开发专用编译方法:

(3)“watch-min”- 产品级编译方法(仅供参考):

五、Eslint代码检测及修复工具配置

六、React 及 react-router-dom4 应用配置


 

一、主要npm包的版本号


{
    "react": "^15.3.1"
    "react-dom": "^15.3.1",
    "react-router-dom": "^4.2.2"
    "antd": "^2.5.2",
    "webpack": "^3.10.0",
    "webpack-dev-server": "^2.7.1"
}

 

二、项目结构介绍


>static   
    >app                         `业务代码文件夹`
        >components              `木偶组件`
           >Tooltip.jsx          `Tooltip文字提示组件,可复用`
        ----------------------------------------------------------------------
        >containers              `智能组件(主要页面)`
           >index                `首页文件夹`
              >index.jsx         `首页`
              >subpage           `首页专有组件文件夹`
              >style             `首页专有样式`
        ----------------------------------------------------------------------
        >templateHtml       `html模板文件,webpack打包后以此模版为原型生成新的html`
        >images             `图片`  
        >plugins            `插件`
        >router             `路由配置`
        >styles             `公共样式`
        >index.js           `入口文件index.js`
        >login.js           `入口文件login.js`
    --------------------------------------------------------------------------       
    >built                 `打包后自动生成的built文件夹,无需手动创建` 
        >branch            `存放按需加载的组件` 
        >css               `样式`
        >fonts             `fonts`
        >img               `img`
        >index.bundle.js   `index文件`
        >login.bundle.js   `login文件`
        >vendor.bundle.js  `第三方依赖` 
    --------------------------------------------------------------------------    
    >html            `打包后自动生成的html文件夹,修改html请在app/templateHtml文件中修改`
        >index.html  `自动生成的html,自动引入built中的文件,可加载带hash值的文件`
        >login.html  `自动生成的html,自动引入built中的文件,可加载带hash值的文件`
    --------------------------------------------------------------------------
    >node_modules
    --------------------------------------------------------------------------
    >.babelrc                 `babel配置文件`
    >.eslintrc.js             `eslint配置文件`
    >build.bat                `自定义build打包命令的批处理文件` 
    >cnpm.bat                 `cnpm批处理文件` 
    >package.json             `package.json配置文件`
    >postcss.config.js        `postcss配置文件` 
    >watch-dev.bat            `自定义watch-dev打包命令的批处理文件`
    >watch-min.bat            `自定义watch-min打包命令的批处理文件`
    >webpack.dev.config.js    `watch-dev打包命令所对应webpack配置文件`
    >webpack.min.config.js    `watch-min打包命令所对应webpack配置文件`
    >webpack.pro.config.js    `watch-build打包命令所对应webpack配置文件`  

 

三、package.json配置


(1)基本环境配置

           首先确保你的电脑已经安装了NodeJS,NodeJS官网可以提供下载。

           然后在项目文件路径下,运行指令 npm init ,初始化项目:

npm init

运行 npm init 之后会要求回答一些基本问题,然后会在当前目录下自动生成一个基本的 package.json 文件。

Webpack 安装 (指定版本:[email protected]):

cmd工具中,输入命令 :

npm install [email protected] --save-dev

(2)淘宝 NPM 镜像:

使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具可以代替默认的 npm

在项目根文件目录下创建一个 cnpm.bat 批处理文件,加入以下内容:

npm --registry=https://registry.npm.taobao.org --cache=%USERPROFILE%/.npm/.cache/cnpm --disturl=https://npm.taobao.org/dist --userconfig=%USERPROFILE%/.cnpmrc %*

现在可以使用 cnpm 代替 npm 命令了,当网络不通畅时,这个中间镜像可以帮助程序猿保持持续的战斗力哦。

如使用cnpm 安装 webpack:

cnpm install [email protected] --save-dev

(2)配置webpack打包命令:

在本项目中定义了三种 webpack打包命令,分别是"build"、"watch-dev"、"watch-min",所对应的webpack配置文件分别是webpack.dev.config.js、webpack.dev.config.js、webpack.min.config.js。

在 package.json同级目录下创建这三个webapck的config空文件,然后在package.json的 scripts 中将打包命令与webpack的config文件绑定:

"scripts":{
    "build": "set NODE_ENV=production && webpack --config ./webpack.pro.config.js --progress --colors",
    "watch-dev": "set NODE_ENV=dev && webpack --config ./webpack.dev.config.js --progress --colors --watch",
    "watch-min": "set NODE_ENV=production && webpack --config ./webpack.min.config.js --progress --colors --watch"
  }

上述代码中 " set NODE_ENV = dev "设置环境变量为开发环境;"set NODE_ENV = production"设置环境变量为生产环境;添加"--watch"可设置为实时编译,在此为"watch-dev”和"watch-min"命令设置实时编译;

 

配置webpack打包命令的批处理文件:

为了更加方便使用命令,建议为每个打包命令配置一个.bat(批处理文件)。可以更加简短的使用命令

build 命令,在package.json同级目录下,创建 build.bat文件,并写入:

cnpm run build

此时,我们就可以直接使用cmd工具,输入build 即可打包项目了。

同理,配置watch-dev.bat文件:

cnpm run watch-dev

watch.min.bat文件:

cnpm run watch-min

package.json代码展示:

{
  "name": "ReactDemo",
  "version": "1.0.0",
  "description": "React + React-router4 + Webpack3 + less + Antd",
  "main": "index.js",
  "scripts": {
    "build": "set NODE_ENV=production && webpack --config ./webpack.pro.config.js --progress --colors",
    "watch-dev": "set NODE_ENV=dev && webpack --config ./webpack.dev.config.js --progress --colors --watch",
    "watch-min": "set NODE_ENV=production && webpack --config ./webpack.min.config.js --progress --colors --watch",
  },
  "repository": {
    "type": "svn",
    "url": "https://me.csdn.net/m0_37128507"
  },
  "author": "ChiWen",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^3.10.0"
  },
  "dependencies": {
  }  
}

 

四、Webpack3配置方法介绍


本项目使用的 webpack 是 3.10.0 版本,同时配置了三种打包方式,第一种"build":生成经过压缩且带哈希值的文件,非常适用于产品发布;第二种“watch-dev”:代码没有压缩,没有哈希值,优点是实时编译,反应灵敏,适用于前端开发;第三种“watch-min”:代码经过压缩,实时编译,但文件名没有哈希值,缺点是编译速度慢,仅供参考使用。

(1)“build”- 产品级编译方法:

文件目录:static > webpack.pro.config.js

配置简析

4.1  在webpack.pro.config.js文件中引入路径处理模块 path,以及webpack模块,同时暴露出一个对象module.exports = {}

const path = require('path');
const webpack = require('webpack');

 

4.2  entry: 除了配置业务代码index.js和login.js入口文件,建议配置vendor,将第三方依赖包(如react, react-dom, react-router-dom, antd等)单独包装,生成vendor.bundle.js。

module.exports = {
    entry: {
        index: "./app/index.js",
        login: "./app/login.js",
        vendor: [
            'react',
            'react-dom',
            'react-router-dom',
            'antd'
        ]
    },
    //........
}

 

4.3 output: 使用chunkhash为每个文件名附加哈希值,以解决浏览器缓存问题。filename:入口文件名;chunkFilename:非入口文件名。

output: {
        path: path.resolve(__dirname, 'built'),
        publicPath: '/built/',
        filename: "[name].bundle.[chunkhash:8].js",
        chunkFilename: 'branch/[name].bundle.[chunkhash:8].js'
}

 

4.4  devtool:控制是否以及如何生成 source map(源映射)。选择一种 source map 格式来增强调试过程,不同的值会明显影响到构建(build)和重新构建(rebuild)的速度。下面介绍两种常用的source map格式:

devtool : ' none ' 构建与重构建速度非常快,生成更精准的 source map,从 bundle 中分离并独立存在,适合生产环境。

devtool : ' eval-source-map ' 构建与冲构建速度不及none模式,但优点是可以保证原始源代码的品质,适合开发环境。

在webpack.pro.config.js中,我们选用适合生产环境的 devtool:' none ':

devtool: 'none'

 

4.5  resolve: 配置默认扩展名,能够在引入模块时无需带扩展名,本项目使用的是React框架,jsx 和 js 用的比较多。

resolve: {extensions: ['.js', '.jsx']}

 

4.6. 使用 babel 转译JavaScript文件。

安装 babel-corebabel-loader。babel-core:babel转译器本身,提供了babel转译的api;babel-loader:配合webpack调用 babel-core 提供的 API 对 JS 文件进行转译。

npm install babel-core babel-loader --save-dev

           安装babel转译过程中需要使用的插件:

npm install babel-preset-env babel-preset-react babel-preset-stage-0 --save-dev

            webpack.pro.config.js中配置处理javaScript文件的模块。

 module: {
        rules: [
            {
                test: /\.(js|jsx)$/, 
                exclude: /(node_modules|bower_components)/, 
                loader: 'babel-loader'
            }
       ]
}

在根目录下新建babel配置文件文件: babel.rc。为了避免webpack.pro.config.js文件过于臃肿,建议把babel的配置分离出来,放到babel.rc文件中。

babel-preset-env 是一个新的 preset,可以根据配置的目标运行环境(environment)自动启用需要的 babel 插件。babel团队建议使用babel-preset-env而不是继续每年的预置。参考链接:http://babeljs.io/docs/en/env/

babel-preset-react:如果要编译jsx文件,则需预设 react 模块;

babel-preset-stage-0: ” stage-0 "是对ES7一些提案的支持,Babel通过插件的方式引入,让Babel可以编译ES7代码。stage-0 包含stage-1, stage-2以及stage-3的所有功能。如果为了防止开发人员使用太新的语法,可以在presets中限制到某个stage即可。

{
  "presets": [
    [ "env" ],
    "react",
    "stage-0"
  ],
  "plugins": []
}

本项目依赖 Antd 组件及样式,如果将 Antd 的组件和样式全部引入,必然会对前端性能造成隐患,因此我们可以在babel中的 plugins 中设置按需加载。(参考 Ant Design 关于 babel-plugin-import 引入组件和样式的配置说明:https://2x.ant.design/docs/react/introduce-cn)。

先安装 babel-plugin-importbabel-plugin-import是一个用于按需加载组件代码和样式的 babel 插件

npm install babel-plugin-import --save-dev

然后在 babel.rc 中设置如下:

{
  "presets": [
    [ "env" ],
    "react",
    "stage-0"
  ],
  "plugins": [
    [
      "import",
      {
        "libraryName": "antd",
        "style": "css"
      }
    ]
  ]
}

           这样,关于编译js文件的基本配置就已经完成。下面对css文件的编译进行设置。

4.7. 分离css文件。对于生产环境的构建,建议使用extract-text-webpack-plugin,将从 bundle 中提取 CSS,以便之后可以并行加载 CSS/JS 资源。同时配置压缩css代码功能、自动添加浏览器前缀功能。首先安装使用npm安装:

npm install --save-dev extract-text-webpack-plugin

● 引入extract-text-webpack-plugin,为以入口文件名命名新的css文件:

const ExtractTextPlugin = require('extract-text-webpack-plugin');

const cssExtractor = new ExtractTextPlugin({
    filename: 'css/[name].min.[chunkhash:8].css',
    allChunks: true
});

● plugins中引入刚才定义的 cssExtractor

module.exports = {
    //...

    module: {
        rules: [
            //...
            cssExtractor, //分离css
        ]
    }
};

● 在webpack中需要处理css必须先安装css-loaderstyle-loader

npm install --save-dev css-loader style-loader

● 安装less,处理 less文件必须安装less-loader

npm install --save-dev less less-loader

● 添加浏览器前缀需要安装 postcss-loader Autoprefixer 插件。Autoprefixer是一款自动管理浏览器前缀的插件,它可以解析CSS文件并且添加浏览器前缀到CSS内容里。

npm install --save-dev postcss-loader autoprefixer

● 下面在module中定义规则处理css文件,使用刚才定义的cssExtractor方法,在css-loader后面添加options:{ minimize:true }用于压缩css代码,这里要注意loader的顺序,postcss-loader 必须在 css-loader之后添加。具体代码如下:

 module: {
        rules: [
            {
                test: /\.css$/,
                use: cssExtractor.extract({
                    use: [{
                        loader: "css-loader",
                        options: {
                            minimize: true
                        }
                    },{
                        loader: 'postcss-loader'
                    }],
                    fallback: "style-loader"
                })
            }
        ]
    },

● 同理,定义处理less文件的规则如下所示:

module: {
        rules: [
            {
                test: /\.less$/i,
                use: cssExtractor.extract({
                    use: [{
                        loader: "css-loader",
                        options: {
                            minimize: true
                        }
                    },{
                        loader: 'postcss-loader'
                    },{
                        loader: "less-loader"
                    }],
                    fallback: "style-loader"
                })
            }
        ]
    },

● 定义完规则后,应在同级目录下创建postcss.config.js,引入 autoprefixer 插件:

module.exports = {
    plugins: [
        require('autoprefixer')
    ]
};

● 尝试写一些样式,你会发现编译后的css被自动加上浏览器前缀了:

           4.8 url-loader 处理 css 中的图片字体资源。url-loader 功能类似于 file-loader,但是在文件大小(单位 byte)低于指定的限制时,可以返回一个 DataURL。[email protected] 版本需要同时按照 file-loader , [email protected]版本则不必依赖file-loader,但依赖于[email protected]版本。本项目中使用[email protected]版本。

npm install [email protected] file-loader --save-dev

           ● 在webpack.pro.config.js文件中的module中处理图片字体资源的模块:

{
    test: /\.(png|gif|jpg|jpeg|bmp)$/i, 
    loader: 'url-loader?limit=5000&name=img/[name].[hash:8].[ext]'
},
{
    test: /\.(woff|woff2|svg|ttf|eot)($|\?)/i,
    loader: 'url-loader?limit=5000&name=fonts/[name].[hash:8].[ext]'
}

         上述代码第一条配置是处理图片资源(如png, gif, jpg, jpeg, bmp等),引入url-loader,并且限制limit = 5000,超过5000byte的文件会存储在根目录下build\img文件夹中,同时给文件加上hash值([hash:8])。

            第二条配置是处理字体资源(如woff, woff2, svg, ttf, eot等),配置参数可参考第一条。

          

           4.9 webpack.pro.config.js 中的 plugins 配置。

           ● webpack内置插件 BannerPlugin 为每个 chunk 头部添加 banner 。

module.exports = {

    //.....

    plugins: [

        new webpack.BannerPlugin('版权所有,翻版必究!'),
    ]
};

● webpack内置插件 OccurrenceOrderPlugin 用于排序输出,删除重复数据,可以有效减少文件大小,提高打包性能,建议在生产环境下使用。

new webpack.optimize.OccurrenceOrderPlugin()

● webpack内置插件 UglifyJsPlugin 压缩js文件:

new webpack.optimize.UglifyJsPlugin({
     compress: {
          warnings: false
     }
})

● webpack内置插件 CommonsChunkPlugin 提取公共代码。CommonsChunkPlugin 插件,是一个可选的用于建立一个独立文件(又称作 chunk)的功能,这个文件包括多个入口 chunk 的公共模块。通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存起来到缓存中供后续使用。这个带来速度上的提升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次访问一个新页面时,再去加载一个更大的文件。

new webpack.optimize.CommonsChunkPlugin({
     name: 'vendor',
     filename: '[name].bundle.[chunkhash:8].js'
}),

为了更加明确地拆分公共代码和应用代码,建议在 entry 定义一个第三方入口 vendor,将第三方插件统一打包成相对固定不变的文件,从浏览器缓存角度看,这样可以减少公共代码的改变, 提升前端性能。

entry: {
        index: "./app/index.js",
        vendor: [
            'react',
            'react-dom',
            'react-router-dom',
            'antd'
        ]
}

● webpack内置插件 DefinePlugin 创建一个在编译时可以配置的全局常量。

在Node有全局变量 process 表示当前node进程,process.env 包含着关于系统环境的信息。在前端工程化配置中,常常使用NODE_ENV作为判断生产环境或开发环境的依据。可以在服务启动时配置NODE_ENV,或者在代码中设置process.env.NODE_ENV。下面是在 webpack.pro.config.js 中使用 DefinePlugin 设置 默认NODE_ENV

new webpack.DefinePlugin({
    "process.env": {
         NODE_ENV: JSON.stringify('production')
     }
}),

也可以在项目 package.json的 scripts 命令中设置NODE_ENV,如果scripts.build 脚本没有设置NODE_ENV,缺省值为'development'。windows系统环境下设置:

"scripts": {
    "build": "set NODE_ENV=production && webpack --config ./webpack.pro.config.js --progress --colors"
},

CleanWebpackPlugin 删除文件。由于我们使用Webpack打包时创建了带有哈希值的文件,每一次build之前需要删除之前旧的文件,可以使用 CleanWebpackPlugin 。安装 :

npm install [email protected] --save-dev

在webpack.pro.config.js头部引入 CleanWebpackPlugin

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

在plugins中进行配置,第一个参数设置需要删除的文件名称,第二个参数中 root : __dirname 表示根目录( webpack.pro.config.js同一级),verbose:是否打印日志,dry: true 表示不删除任何东西,主要用于测试,此处设为 false。

new CleanWebpackPlugin(
    ['built', 'html'],
    {
        root: __dirname,
        verbose: true,
        dry: false
    }
)

HtmlWebpackPlugin 创建一个新的 HTML5 文件,这对于被更改文件的文件名中包含每次编译哈希(hash) 的webpack bundle尤其有用。该文件的 body 中使用 script 标记引用了所有 webpack bundle。如果有任何CSS资源在webpack的 output 中,(例如,使用 ExtractTextPlugin 提取的CSS)那么这些资源将被包含在 HTML head 中,使用 <link> 标记引用。

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

webpack.pro.config.js文件引入HtmlWebpackPlugin

const HtmlWebpackPlugin = require('html-webpack-plugin');

然后需要准备一个模板html文件,在根目录下app应用代码文件中创建一个 templateHtml 的文件夹,分别创建index.html 和 login.html。无需手动引入bundle文件,webpack打包后会自动在引入bundle文件,特别是对于需要引入带有哈希值的文件来说,非常方便。

需要注意的是,thunks数组中入口文件的排序,第三方依赖包 vendor 应该排在第一位。

plugins中配置如下:

//配置index.html
new HtmlWebpackPlugin({
    filename: "./../html/index.html", 生成的新html文件目录,与入口文件相对的路径
    template: './app/templateHtml/index.html', //模板文件目录,与webpack.pro.config.js相对的路径
    thunks: ['vendor', 'index'], // 引入entry中定义的入口文件
    excludeChunks: ['login'] //排除不需要引入的入口文件
}),

//配置login.html
new HtmlWebpackPlugin({
    filename: './../html/login.html',
    template: './app/templateHtml/login.html',
    thunks: ['vendor', 'login'],
    excludeChunks: ['index']
}),

webpack执行打包命令后会在根目录下生成一个html文件夹。

自动引入带有 hash 值的 bundle文件:

 

至此,webpack.pro.config.js的生产环境配置已经完成了!完整webpack.pro.config.js代码如下:

代码展示:

/**
 * Created by ChiWen([email protected]).
 * name: webpack.pro.config.js
 * command: build
 */
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const cssExtractor = new ExtractTextPlugin({
    filename: 'css/[name].min.[chunkhash:8].css',
    allChunks: true
});

module.exports = {
    entry: {
        index: "./app/index.js",
        login: "./app/login.js",
        vendor: [ //将依赖包单独打包
            'react',
            'react-dom',
            'react-router-dom',
            'antd'
        ]
    },

    output: {
        path: path.resolve(__dirname, 'built'),
        publicPath: '/built/',
        filename: "[name].bundle.[chunkhash:8].js", //主入口的文件名
        chunkFilename: 'branch/[name].bundle.[chunkhash:8].js' //非主入口的文件名
    },

    devtool: 'none',

    resolve: {extensions: ['.js', '.jsx']},

    module: {
        rules: [
            {
                test: /\.(js|jsx)$/, 
                exclude: /(node_modules|bower_components)/, 
                loader: 'babel-loader'
            },
            {
                test: /\.css$/,
                use: cssExtractor.extract({
                    use: [{
                        loader: "css-loader",
                        options: {
                            minimize: true
                        }
                    },{
                        loader: 'postcss-loader'
                    }],
                    fallback: "style-loader"
                })
            }, {
                test: /\.less$/i,
                use: cssExtractor.extract({
                    use: [{
                        loader: "css-loader",
                        options: {
                            minimize: true
                        }
                    },{
                        loader: 'postcss-loader'
                    },{
                        loader: "less-loader"
                    }],
                    fallback: "style-loader"
                })
            },
            {
                test: /\.(png|gif|jpg|jpeg|bmp)$/i, 
                loader: 'url-loader?limit=5000&name=img/[name].[hash:8].[ext]'
            },
            {
                test: /\.(woff|woff2|svg|ttf|eot)($|\?)/i,
                loader: 'url-loader?limit=5000&name=fonts/[name].[hash:8].[ext]'
            }
        ]
    },

    plugins: [

        //为每个 chunk 文件头部添加 banner
        new webpack.BannerPlugin('版权所有,翻版必究!'), 

        //调整模块的打包顺序,用到次数更多的会出现在文件的前面
        new webpack.optimize.OccurrenceOrderPlugin(),

        //压缩js文件
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            }
        }),

        // 提供公共代码
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            filename: '[name].bundle.[chunkhash:8].js'
        }),

        //定义环境变量
        new webpack.DefinePlugin({
            "process.env": {
                NODE_ENV: JSON.stringify('production')
            }
        }),

        //打包之前删除built和html文件夹
        new CleanWebpackPlugin(
            ['built', 'html'],
            {
                root: __dirname,
                verbose: true,
                dry: false
            }
        ),

        //配置index.html
        new HtmlWebpackPlugin({
            filename: "./../html/index.html",
            template: './app/templateHtml/index.html',
            thunks: ['vendor', 'index'],
            excludeChunks: ['login']
        }),

        //配置login.html
        new HtmlWebpackPlugin({
            filename: './../html/login.html',
            template: './app/templateHtml/login.html',
            thunks: ['vendor', 'login'],
            excludeChunks: ['index']
        }),

        cssExtractor //分离css
    ]
};

 

(2)“watch-dev”- 前端开发专用编译方法

文件目录:static > webpack.dev.config.js

配置简析:代码无压缩,文件无哈希值,编译速度快。具体配置可参考webpack.pro.config.js。

代码展示:

/**
 * Created by ChiWen([email protected]).
 * name: webpack.dev.config.js
 * command: watch-dev
 */
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const cssExtractor = new ExtractTextPlugin({
    filename: 'css/[name].min.css',
    allChunks: true
});

module.exports = {
    entry: {
        index: "./app/index.js",
        login: "./app/login.js",
        vendor: [
            'react',
            'react-dom',
            'react-router-dom',
            'antd'
        ]
    },

    output: {
        path: path.resolve(__dirname, 'built'),
        publicPath: '/built/',
        filename: "[name].bundle.js",
        chunkFilename: 'branch/[name].bundle.js'
    },

    devtool: 'eval-source-map', //开发时使用eval-source-map

    resolve: {extensions: ['.js', '.jsx']},

    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader'
            },
            {
                test: /\.css$/,
                use: cssExtractor.extract({ //开发时不建议压缩,节省编译时间
                    use: [{
                        loader: "css-loader",
                    },{
                        loader: 'postcss-loader'
                    }],
                    fallback: "style-loader"
                })
            }, {
                test: /\.less$/i,
                use: cssExtractor.extract({
                    use: [{
                        loader: "css-loader",
                    },{
                        loader: 'postcss-loader'
                    },{
                        loader: "less-loader"
                    }],
                    fallback: "style-loader"
                })
            },
            {
                test: /\.(png|gif|jpg|jpeg|bmp)$/i,
                loader: 'url-loader?limit=5000&name=img/[name].[ext]'
            },
            {
                test: /\.(woff|woff2|svg|ttf|eot)($|\?)/i,
                loader: 'url-loader?limit=5000&name=fonts/[name].[ext]'
            }
        ]
    },

    plugins: [

        new webpack.BannerPlugin('版权所有,翻版必究!'),

        new webpack.optimize.OccurrenceOrderPlugin(),

        // 提供公共代码
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            filename: '[name].bundle.js'
        }),

        new webpack.DefinePlugin({
            "process.env": {
                NODE_ENV: JSON.stringify('dev') //设置环境变量为'dev'
            }
        }),

        //①index.html
        new HtmlWebpackPlugin({
            filename: "./../html/index.html",
            template: './app/templateHtml/index.html',
            thunks: ['vendor', 'index'],
            excludeChunks: ['login']
        }),

        //②login.html
        new HtmlWebpackPlugin({
            filename: './../html/login.html',
            template: './app/templateHtml/login.html',
            thunks: ['vendor', 'login'],
            excludeChunks: ['index']
        }),

        cssExtractor //分离css
    ]
};

(3)“watch-min”- 产品级编译方法(仅供参考):

文件目录:static > webpack.min.config.js

配置简析:代码经过压缩,实时编译,文件无hash值,但编译速度较慢。具体配置参考webpack.pro.config.js。

代码展示:

/**
 * Created by ChiWen([email protected]).
 * name: webpack.min.config.js
 * command:watch-min
 */
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const cssExtractor = new ExtractTextPlugin({
    filename: 'css/[name].min.css',
    allChunks: true
});

module.exports = {
    entry: {
        index: "./app/index.js",
        login: "./app/login.js",
        vendor: [
            'react',
            'react-dom',
            'react-router-dom',
            'antd'
        ]
    },

    output: {
        path: path.resolve(__dirname, 'built'),
        publicPath: '/built/',
        filename: "[name].bundle.js",
        chunkFilename: 'branch/[name].bundle.js'
    },

    devtool: 'none',

    resolve: {extensions: ['.js', '.jsx']},

    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader'
            },
            {
                test: /\.css$/,
                use: cssExtractor.extract({
                    use: [{
                        loader: "css-loader",
                        options: {
                            minimize: false
                        }
                    },{
                        loader: 'postcss-loader'
                    }],
                    fallback: "style-loader"
                })
            }, {
                test: /\.less$/i,
                use: cssExtractor.extract({
                    use: [{
                        loader: "css-loader",
                        options: {
                            minimize: false
                        }
                    },{
                        loader: 'postcss-loader'
                    },{
                        loader: "less-loader"
                    }],
                    fallback: "style-loader"
                })
            },
            {
                test: /\.(png|gif|jpg|jpeg|bmp)$/i,
                loader: 'url-loader?limit=5000&name=img/[name].[ext]'
            },
            {
                test: /\.(woff|woff2|svg|ttf|eot)($|\?)/i,
                loader: 'url-loader?limit=5000&name=fonts/[name].[ext]'
            }
        ]
    },

    plugins: [

        new webpack.BannerPlugin('版权所有,翻版必究!'),

        new webpack.optimize.OccurrenceOrderPlugin(),

        //压缩js文件
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            }
        }),

        // 提供公共代码
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            filename: '[name].bundle.js'
        }),

        new webpack.DefinePlugin({
            "process.env": {
                NODE_ENV: JSON.stringify('production')
            }
        }),

        //①index.html
        new HtmlWebpackPlugin({
            filename: "./../html/index.html",
            template: './app/templateHtml/index.html',
            thunks: ['vendor', 'index'],
            excludeChunks: ['login']
        }),

        //②login.html
        new HtmlWebpackPlugin({
            filename: './../html/login.html',
            template: './app/templateHtml/login.html',
            thunks: ['vendor', 'login'],
            excludeChunks: ['index']
        }),

        cssExtractor //分离css
    ]
};

五、Eslint代码检测及修复工具配置

篇幅有限,请点击 https://blog.csdn.net/m0_37128507/article/details/82802261查看Eslint文章哦^_^

六、React 及 react-router-dom4 应用配置

篇幅有限,请点击进入主页  https://blog.csdn.net/m0_37128507 查看相关文章哦^_^


                                                                                             --- END ---

猜你喜欢

转载自blog.csdn.net/m0_37128507/article/details/82683546