经过三个章节的学习,你已经学会搭建了一个基于webpack4的react脚手架。如果要更改配置,比如,你希望把编译后的js文件和css文件等单独放dist下的static目录下,你想想,是不是有点麻烦。你要去浏览webpack的配置文件,找到哪些配置项,然后去更改它,我们希望有个参数配置文件,只要更改参数配置,而无需更改webpack的配置文件。
(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目录下了。你可以修改参数配置文件,然后试试看吧。
(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: 8080, ????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, ???}
(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: 8080, ???????????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: 1, ???????????????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 脚手架(四)
原文地址:https://www.cnblogs.com/nianzhilian/p/webpack.html