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

react

经过三个章节的学习,你已经学会搭建了一个基于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: 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,

}

更多的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: 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 脚手架(四) 的全部内容, 来源链接: utcz.com/z/383463.html

回到顶部