经过三个章节的学习,你已经学会搭建了一个基于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. SpringMVC 监听文件上传进度

    Spring MVC 监听文件上传进度 具体实现分三个步骤: 接管CommonsMultipartResolver,重写针对文件上传的请求. 在第一步中写入监听,以获取上传进度. 修改上传部分的配置文 ...

  2. 升级AndroidStudio3.4问题汇总

    1.Could not get unknown property 'bootClasspath' for object of type org.gradle.api.tasks.compile.Com ...

  3. (二叉树 递归) leetcode 889. Construct Binary Tree from Preorder and Postorder Traversal

    Return any binary tree that matches the given preorder and postorder traversals. Values in the trave ...

  4. C语言 内存管理(转)

     转自 https://blog.csdn.net/u011616739/article/details/61621815 C语言 内存管理 1.内存分区 C源代码进过预处理.编译.汇编和链接4步生成 ...

  5. hadoop记录-hadoop常用

    1.hdfs目录配额 #设置配额目录hdfs dfsadmin -setSpaceQuota 10T /user/hive/warehouser/tmp查看配额目录信息hdfs dfs -count ...

  6. hadoop记录-浅析Hadoop中的DistCp和FastCopy(转载)

    DistCp(Distributed Copy)是用于大规模集群内部或者集群之间的高性能拷贝工具. 它使用Map/Reduce实现文件分发,错误处理和恢复,以及报告生成. 它把文件和目录的列表作为ma ...

  7. 微信小程序button组件样式

    点击微信按键组件才能出授权,所以自定义样式就是必须的了,来自网友的帮助,如下图 <button class='btn1' open-type='contact'> <image cl ...

  8. AtCoder Grand Contest 030题解

    第一次套刷AtCoder 体验良好 传送门 Poisonous Cookies cout<<b+min(c,a+b+); Tree Burning 难度跨度有点大啊 可以证明当第一次转向之 ...

  9. 题解:[GXOI/GZOI2019]与或和

    开始完全没思路 在洛谷看到样例一,突发奇想,决定先做一下元素只有0/1的情况 发现子任务1是全1子矩阵 子任务2是总子矩阵个数减去全0子矩阵 发现全0/1矩阵可以构造单调栈解决.具体做法:前缀和求出每 ...

  10. Request method 'POST' not supported解决办法

    (1)考虑拦截器是否将该链接拦截