经过三个章节的学习,你已经学会搭建了一个基于webpack4的react脚手架。如果要更改配置,比如,你希望把编译后的js文件和css文件等单独放dist下的static目录下,你想想,是不是有点麻烦。你要去浏览webpack的配置文件,找到哪些配置项,然后去更改它,我们希望有个参数配置文件,只要更改参数配置,而无需更改webpack的配置文件。

1 添加参数配置文件
(1)在根目录创建config文件夹,在config文件夹内新建一个index.js文件,文件内容如下:
    'use strict'

    const path = require('path')

    module.exports = {
dev: {
assetsSubDirectory: 'static',
assetsPublicPath: '/',
},
build: {
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
}
}

我们定义了一部分配置参数,顾名思义,dev属性下的参数配置是针对开发环境,build属性下的参数配置是针对生产环境的。其中,assetsRoot是编译后的文件存放根路径,assetsSubDirectory是资源文件编译后存放的文件夹名称,assetsPublicPath是公共的路径。

(2)修改webpack.base.conf.js,如下
    const path = require('path');
const config=require('../config');
const APP_PATH = path.resolve(__dirname, '../app'); module.exports = {
entry: {
app: './app/index.js',
framework: ['react', 'react-dom'],
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
module: {
rules: [
{
test: /\.js?$/,
use: "babel-loader",
include: APP_PATH
}
]
}
};

注意:我们在webpack.base.conf.js内配置了filename,那么dev环境下默认使用该配置,可以删除webpack.dev.conf.js内关于output的配置。

(3)路径生成方法:

路径的配置需要由assetsPublicPath和assetsSubDirectory以及具体的子路径组成,我们写一个公共的方法来生成路径。无论是开发环境还是生产环境,我们都可以复用该方法。我们在build文件夹下建立一个utils.js文件。内容如下:

    const path = require('path')
const config = require('../config') exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory return path.posix.join(assetsSubDirectory, _path)
}
(4)修改webpack.prod.conf.js

在webpack.prod.conf.js页面头部引入

    const config=require('../config');
const utils=require('./utils');

修改output属性的内容

     output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash:16].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},

修改plugins内的相关配置:

    new CleanWebpackPlugin([config.build.assetsRoot], { allowExternal: true }),

    //导出css
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].[hash].css'),
chunkFilename: utils.assetsPath('css/[id].[hash].css'),
}),
(5)执行编译命令查看
npm run build

查看编译后的文件是否放在static目录下了。你可以修改参数配置文件,然后试试看吧。

2 更多的配置化
 
接下去我们会把更多的参数和变量进行配置化。
(1)index.html HTML模板的位置

在config.js文件的dev和build参数下都配置index属性:

index: path.resolve(__dirname, '../public/index.html'),

修改HtmlWebpackPlugin内template的值:
webpack.prod.conf.js的相关修改:

     new HtmlWebpackPlugin({
template: config.build.index,
inject: 'body',
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
}),

webpack.dev.conf.js的相关修改:

    new HtmlWebpackPlugin({
template: config.dev.index,
inject: true
}),
(2)增加devServer 的配置

dev环境下,启动的端口号,代理相关,以及是否自动打开浏览器等等推荐可以放在参数配置文件内。
在config.js文件内增加相关配置参数:

    proxyTable: {},
host: 'localhost',
port: ,
autoOpenBrowser: true,

修改webpack.dev.conf.js内的相关配置:

     devServer: {
host: config.dev.host,
port: config.dev.port,
contentBase: path.join(__dirname, '../public'),
compress: true,
historyApiFallback: true,
hot: true,
https: false,
noInfo: true,
open: config.dev.autoOpenBrowser,
proxy: config.dev.proxyTable,
}
更多的css loader加载器
 
我们在loader中配置了less加载器,如果我们要支持其他呢,比如sass,scss等等,显然,我们需要在rules数组增加配置。其实,这里可以写成公共的生成方法。并且我们把部分参数变成可配置。比如:是否开启cssModule等。
(1)前期准备,增加部分参数配置

修改config.js内的配置:

    const path = require('path')

    module.exports = {
base: {
// 是否开启cssModule
cssModule: true,
// cssModule排除的目录, 其他css库可以放这里
cssModuleExcludePath: /public/
},
dev: {
assetsSubDirectory: 'static',
assetsPublicPath: '/', index: path.resolve(__dirname, '../public/index.html'), proxyTable: {}, host: 'localhost',
port: ,
autoOpenBrowser: true,
// 是否生成sourceMap
cssSourceMap: true, },
build: {
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/', index: path.resolve(__dirname, '../public/index.html'), // 是否生成sourceMap
productionSourceMap: true,
}
}
(2) 在utils.js内增加cssLoaders和styleLoaders方法:
    exports.cssLoaders = function (options) {
options = options || {} let cssLoader = {
loader: 'css-loader',
options: {
importLoaders: ,
sourceMap: options.sourceMap
}
}
if (options.cssModule) {
cssLoader.options.modules = true;
cssLoader.options.localIdentName = '[local]__[hash:7]';
}
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
function generateLoaders(loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
} if (options.extract) {
return [MiniCssExtractPlugin.loader].concat(loaders)
} else {
return ['style-loader'].concat(loaders)
}
} return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less', { javascriptEnabled: true, indentedSyntax: true }),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
} exports.styleLoaders = function (options) {
let output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
let loaderObj = {
test: new RegExp('\\.' + extension + '$'),
use: loader,
}
if (options.cssModule) {
loaderObj.exclude = options.cssModuleExcludePath;
}
output.push(loaderObj)
} if (options.cssModule) {
options.cssModule = false
const cssModuleLoaders = exports.cssLoaders(options)
for (const extension in cssModuleLoaders) {
const cssModuleLoader = cssModuleLoaders[extension]
let cssModuleLoaderObj = {
test: new RegExp('\\.' + extension + '$'),
use: cssModuleLoader,
}
cssModuleLoaderObj.include = options.cssModuleExcludePath;
output.push(cssModuleLoaderObj)
}
}
return output
}
(3) 在webpack.prod.conf.js内使用

确认是否引入了utils,如果没有引入,在页面上方增加代码:

const utils=require('./utils');

修改 module内的rules属性:

    rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true,
cssModule:config.base.cssModule,
cssModuleExcludePath:config.base.cssModuleExcludePath
})

执行编译查看:

npm run build
(4) 在webpack.dev.conf.js内使用

确认是否引入了utils,如果没有引入,在页面上方增加代码:

const utils=require('./utils');

修改 module内的rules属性:

     rules: utils.styleLoaders({
sourceMap: config.dev.cssSourceMap,
usePostCSS: true,
cssModule:config.base.cssModule,
cssModuleExcludePath:config.base.cssModuleExcludePath
})

执行dev命令试试看

npm run dev

下一节会对 如果对编译后的文件进行gzip压缩,如何让开发环境的控制台输出更加高逼格,如何更好的对编译后的文件进行bundle分析等问题展开讨论。

【webpack系列】从零搭建 webpack4+react 脚手架(四)的更多相关文章

  1. 【webpack系列】从零搭建 webpack4+react 脚手架(一)

    搭建一个React工程的方式有很多,官方也有自己的脚手架,如果你和我一样,喜欢刨根究底,从零开始自己一行一行代码创建一个React脚手架项目,那你就来对地方了.本教程是针对React新手,以及对web ...

  2. 【webpack系列】从零搭建 webpack4+react 脚手架(三)

    本章节,我们对如何在脚手架中引入CSS,如何压缩CSS,如何使用CSS Modules,如何使用less,如何使用postcss等问题进行展开学习. 1 支持css (1)在app目录,新建一个css ...

  3. 【webpack系列】从零搭建 webpack4+react 脚手架(二)

    html文件如何也同步到dist目录?bundle.js文件修改了,万一被浏览器缓存了怎么办?如何为导出的文件加md5?如何把js引用自动添加到html?非业务代码和业务代码如何分开打包?如何搭建开发 ...

  4. 【webpack系列】从零搭建 webpack4+react 脚手架(五)

    本章节,我们一起来探讨以下问题:如何对编译后的文件进行gzip压缩,如何让开发环境的控制台输出更加高逼格,如何更好的对编译后的文件进行bundle分析等. 1 gzip压缩 如果你想节省带宽提高网站速 ...

  5. 从零搭建Spring Boot脚手架(1):开篇以及技术选型

    1. 前言 目前Spring Boot已经成为主流的Java Web开发框架,熟练掌握Spring Boot并能够根据业务来定制Spring Boot成为一个Java开发者的必备技巧,但是总是零零碎碎 ...

  6. 初探webpack之从零搭建Vue开发环境

    初探webpack之搭建Vue开发环境 平时我们可以用vue-cli很方便地搭建Vue的开发环境,vue-cli确实是个好东西,让我们不需要关心webpack等一些繁杂的配置,然后直接开始写业务代码, ...

  7. 从零搭建Spring Boot脚手架(2):增加通用的功能

    1. 前言 今天开始搭建我们的kono Spring Boot脚手架,首先会集成Spring MVC并进行定制化以满足日常开发的需要,我们先做一些刚性的需求定制,后续再补充细节.如果你看了本文有什么问 ...

  8. 从零搭建Spring Boot脚手架(3):集成mybatis

    1. 前言 今天继续搭建我们的kono Spring Boot脚手架,上一文集成了一些基础的功能,比如统一返回体.统一异常处理.快速类型转换.参数校验等常用必备功能,并编写了一些单元测试进行验证,今天 ...

  9. 从零搭建Spring Boot脚手架(4):手写Mybatis通用Mapper

    1. 前言 今天继续搭建我们的kono Spring Boot脚手架,上一文把国内最流行的ORM框架Mybatis也集成了进去.但是很多时候我们希望有一些开箱即用的通用Mapper来简化我们的开发.我 ...

随机推荐

  1. MySQL表与表之间的关系

    表与表之间的关系 表1 foreign key 表2 则表1的多条记录对应表2的一条记录,即多对一 利用foreign key的原理我们可以制作两张表的多对多,一对一关系 多对多: 表1的多条记录可以 ...

  2. Multi-View 3D Reconstruction with Geometry and Shading——Part-2

    From PhDTheses Multi-View 3D Reconstruction with Geometry and Shading 我们的主要目标是只利用图像中的信息而没有额外的限制或假设来得 ...

  3. css进度条

    1.环形进度条 源码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...

  4. woe_iv原理和python代码建模

    python信用评分卡(附代码,博主录制) https://study.163.com/course/introduction.htm?courseId=1005214003&utm_camp ...

  5. 【Sublime Text】sublime text 安装插件方法总结

    #使用Package Control组件安装插件 1.安装Package Control组件 按 Ctrl+` 调出console(注:避免热键冲突,可以在界面上操作  View-show conso ...

  6. HTTP协议6之状态码--转

    HTTP状态码,我都是现查现用. 我以前记得几个常用的状态码,比如200,302,304,404, 503. 一般来说我也只需要了解这些常用的状态码就可以了.  如果是做AJAX,REST,网络爬虫, ...

  7. python excel写入及追加写入

    # -*- coding:utf-8 _*- """ @author:Administrator @file: excel.py Description :如果行数是10 ...

  8. UE4 行为树资料

    Composites Select 选择 从左往右执行其子节点,直到一个达成,则 Select 达成并返回上层,否则失败并返回上层 Sequence 队列 从左往右执行其子节点,直到一个失败,则 Se ...

  9. P2P互联网金融企业的四大转型方向

    1.按照国标做成百分百的信息中介平台.这个定位太低,无利可图,如果政策导向真按着这个路径走,未来可能只剩下不到50家平台; 2.转型成为带“民营银行”属性的平台.这还得国家网开一面,学习英国模式,允许 ...

  10. JS 循环定时的一些思考

    网上也有例子, function doSetTimeout(i) { setTimeout(function() { console.log(i); }, 1000); } for (var i = ...