03---webpack进阶用法

本文详细介绍了如何在Webpack配置中处理CSS兼容性、移动端单位转换、资源内联、使用Sourcemap、treeshaking以及服务端渲染(SSR)的实现步骤,同时涵盖了ESLint配置和构建时日志优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

01 自动补齐css的前缀:保证浏览器的兼容问题。需要使用autoprefixer插件和postcss-loader。

webpack.config.js文件中的代码:

module.exports = {

 module:{

    rules:[

     {test:/\.less$/,use:[


        'style-loader',

        'css-loader',

        'less-loader',

        {

            loader:'postcss-loader',

            options:{

                plugins:()=>[require('autoprefixer')({

                    browsers:['last 2 version', '>1%','ios 7']

                })]
            }
        }
    ]}
    
    ]
 }

}

02 移动端css :px自动转化为rem;使用px2rem-loader,同时需要引入手淘的lib-flexible库来完成

webpack.config.js文件中的代码:需要安装npm i px2rem-loader; npm i lib-flexible -s;

module.exports = {

 module:{

    rules:[

     {test:/\.less$/,use:[


        'style-loader',

        'css-loader',

        'less-loader',

        {

            loader:'postcss-loader',

            options:{

                plugins:()=>[require('autoprefixer')({

                    browsers:['last 2 version', '>1%','ios 7']

                })]
            }
        },

        {

            loader:'px2rem-loader',

            options:{

                remUnit:75,  1rem相当于75px 为设计稿的10分之一,配置完会把所有的px转化为rem

                remPrecision:8 转化为rem后面保留的小数
            }
         }
    ]}
    
    ]
 }

}

再然后在项目中index.html 导入 手淘的插件

03 资源内联:页面框架的初始化脚本,上报相关打点,css内联避免页面闪动, 减少http请求。

html与js的内联:

在index.html页面中的<head>头部引入

<script>${require('raw-loader!./meta.html')}</script>

<script>${require('raw-loader!babel-loader!../node_modules/lib-flexible.js')}</script>

css内联 方案一 借助style-loader;

rules:[{

test:'/\.scss$/',

use:[{

    loader:'style-loader',

    options:{

        insertAt:'top', 样式插入到<head>

        singleton:true 将所有style标签合并成一个

   }

}]



}]

css内联 方案二 html-inline-css-webpack-plugin

04 多页面应用打包通用的方案需要动态获取entry和设置html-webpack-plugin的数量,用glob.sync

多页面的入口:entry是一个对象,对应不同的入口文件列入下面:

entry:{

 index:'./src/index/index.js',

 search:'./src/search/index.js'

}

所以得出的规律就是将所有的入口文件放置在src目录下利用脚本自动去进行加载src下的index.js文件

安装glob:npm i glob -D;

在webpack.config.js文件中执行如下的代码:

const glob = require('glob')

const setMPA = ()=>{

 const entry = {}  入口文件

 const htmlWebpackPlugins = []  多个要渲染的模板

 const entryFiles = glob.sync(path.join(__dirname,'./src/*/index.js'))

 Object.keys(entryFiles).map((index)=>{

    const entryFile = entryFiles[index]

    const match = entryFile.match(/src\(.*)\/index\.js/)

    const pageName = match[1]

    entry[pageName] = entryFile

    htmlwebpackPlugins.push(

        new HtmlWebpackPlugin({

            template:path.join(__dirname,`src/${pageName}/index.html`),

            filename:`${pageName}.html`,

            chunks:[pageName]

        })

    )
})

 return {entry, htmlWebpackPlugins}

}

05 使用source map定位到源代码,开发环境开启,线上环境关闭。

在webpack.config.js配置文件中进行添加:

module.exports = {

 devtool:'source-map'

}

06 提取页面公共资源:

基础库分离:

打包的时候,因为需要打包react react-dom等,导致打包的速度会变慢;

解决思路:将react react-dom基础包通过cdn引入,不打入到bundle中

方法:使用 html-webpack-externals-plugin,利用SplitChunksPlugin分离页面公共文件

使用步骤、

第一步 安装 npm i html-webpack-externals-plugin;

第二步 在webpack.config.js文件中导入htmlWebpackExternalsPlugin

第三步 在plugins:[

    new HtmlWebpackExternalsPlugin({

        externals:[

         {
            module:'react',

            entry:'这里是cdn react的地址',
            
            global:'React'

         },

         {
            module:'react-dom',

            entry:'这里是cdn reactdom的地址',
            
            global:'ReactDOM'

         }
        ]

    })
]

第四步  在index.html页面中 通过script标签再导入react和reactDom的CDN的地址;



将页面中多个页面引入的文件打包到dist目录下。配置方法如下:

module.exports = {

 optinization:{

    splitChunks:{

        minSize:0,

        cacheGroups:{

            commons:{
                
                name:'commons',

                chunks:'all',

                minChunks:3 , //至少引入三次才回打包出来
            }

        }
    }
    
 }

}

这里需要在 new HtmlWebpackPlugin({chunks:['vendors',pageName]})添加vendors

07 tree shaking的作用:将项目中定义的方法和变量,实际并没有使用,排除在打包的目录下。

在项目中我们经常会定义一些变量或者方法,在项目中实际并没有被使用,那么在项目打包的使用同时也会将这些没有被使用的变量和方法进行一起打包,这样会造成代码的体积变大。

解决方法:在项目打包的时候将没有被使用到的方法和变量不被打包到dist目录下。

使用步骤: 在webpack.config.js文件中,如果mode模式是production的时候会自动开启tree Shaking的,
不会将没有被使用到的变量和方法打包到dist目录下 

08 scope hoisting:必须是ES6的导入,CJS不支持。

原理:将所有模块的代码按照引用顺序放在一个函数作用域里,然后适当的重命名一些变量以防止变量名的冲突

通过 scope hoisting 可以减少函数声明代码和内存开销

当mode为production的时候会默认开启scope hoisting

09 懒加载js脚本的方式;

ES6:动态import(目前还没有原生的支持,需要babel转换)

首先需要安装babel插件: npm install @babel/plugin-syntax-dynamic-import --save-dev;

将babel插件放在.babelrc的文件中:{'plugins':['@babel/plugin-syntax-dynamic-import']}

使用方法如下:

第一步 首先创建一个需要加载的组件比如:text.js代码如下

import React from 'react'

export default ()=>{<div>测试的组件</div>}

第二步index.js组件中动态的加载text这个组件,比如在点击div元素后进行加载;

import React from 'react'

class Index extends React.Component {

  constructor(){

    super(...arguments)

    this.state = {Text:null}
  }
 
  render(){

     const loadAsync = ()=>{

           import('./text.js').then(res=>{

                this.setState({Text:res.default})
            })
     }

      return <div>
         
         <div onClick={loadAsync}>异步加载test组件</div>

         <span>{Text}</span> // 异步使用组件

      </div>
    }

}

10 在webpack中使用eslint

第一步 项目中安装相关的eslint的插件:

npm i eslint eslint-plugin-import eslint-plugin-react eslint-plugin-jsx-ally -D

npm i eslint-loader  babel-eslint  eslint-config-airbnd -D

第二步 在webpack.config.js文件中进行配置

module.exports = {

 module:{

    rules:[

        {test:/.js$/,

        use:['babel-loader','eslint-loader']

        }
    ]

 }

}

第三步 创建eslint配置文件 .eslintrc.js

module.exports = {
 
  "parser":"babel-eslint",

  "extends":"airbnd",

  "env":{"browser":true,"node":true},

   "rules":{

        "semi":"error"
    }

}

11 webpack打包组件和打包库,可以将打包完的组件库发布到npm上面去

要求:封装一个求大数的方法,这个方法可以通过es6和componentJs引入,同时需要打包正常的版本,和压缩的两个版本。

实现思路:

第一步 通过npm init -y; 创建一个项目

第二步 安装npm i webpack webpack-cli 

第三步 创建src/index.js 这里实现的是大数相加的方法 需要向外导出 

第四步 创建webpack.config.js文件

module.exports = {
 
mode:'none'


entry:{
 
   'large-number':'./src/index.js',  不需要压缩的

   'large-number.min':'./src/index.js' 需要压缩的

 },

   
 output:{
        
     filename:'[name].js',

     library:'largeNumber',

     libraryTarget:'umd'  各种可以导出的方法
    
    },

  optimization:{
    
        minimize:true,

        minimozer:[

            new TerserPlugin({include:/\.min\.js/$}) 将带有min进行压缩
        ]

    }


}


注意点:这里需要安装和引入 TerserPlugin 


接下来我们可以在项目中的根目录定义一个index.js文件 用来区分是开发环境还是生产环境

index.js文件代码如下:

if(process.env.NODE_ENV === 'production'){
 
    module.exports = require('./dist/large-number.min.js')

}else{
    
     module.exports = require('./dist/large-number.js')

}

在文件中直接导入上面这个index.js文件使用便可

 12 webpack实现SSR打包

服务端渲染SSR是什么? 总结就是为了减少请求。

正常的客户端渲染:HTML+CSS+JS+DATA--->渲染后的HTML

客户端渲染需要发送多个请求(HTML 数据等)

加载过程使用的是串行加载(html&数据串行加载)



服务端:所有的模板等资源都存储在服务端, 内网机器拉取数据更快 一个HTML返回所有的数据。

服务端只需要一个请求,返回HTML和数据  服务端渲染


使用步骤:服务端的代码 第一步创建服务端使用express

app.js代码如下:

if(typof window === 'undefiend') {global.window = {}}

const express = require('express')

const {renderToString} = require('react-dom/server')

const SSR = require('../dist/search-server.js') // 这里加载的是webpack打包后的压缩的js文件

server(process.env.PORT || 3000)

const server = (port)=>{
  
  const app = express()

  app.use(express.static('dist'))

  app.get('/search',(req,res)=>{
    
    res.status(200).send(renderMarkup(renderToString(SSR)))

  })

  app.listen(port,()=>{

     console.log('Server is running on port')
  })
}

const renderMarkup(str)=>{
    
    return `<!dectype HTML>

                <body>

                    <div id="root">${str}</div>
            
                </body>
                
            </HTML>`

}


第二步 客户端的代码:

创建 search-server.js

const React = require('react')  //这里需要使用comjs导入 

const Search extends React.Component {

   render(){

        return <div></div>
    }

}

module.exports = <Search/>


第三步 解决样式没有显示的问题

使用打包出来的index.html模板,因为打包后的index.html会自动导入到项目中

在服务端app.js文件中将打包后的index.html进行导入

const fs = require('fs')

const path = require('path')

const data = require('./data.json') // 这是json格式的数据也是要渲染到客户端

const template = fs.readFileSync(path.join(__dirname,'../dist/index.html'),'uft-8')

然后修改renderMarkup函数:

const renderMarup = (str)=>{

    const dataStr = JSON.stringify(data)


    return template.replace('<!--HTML_PLACEHOLDER-->',str).replace('<!--

INITIAL_DATA_PLACEHOLDER-->',`<script>window.__initial_data=${dataStr}</script>`)

}


第四步 在模板的index.html页面中使用占位符 

index.html

<body> 

<div id='root'> <!--HTML_PLACEHOLDER--></div>    这里是HTML占位符

<!--INITIAL_DATA_PLACEHOLDER--> // 这里是JSON数据的占位符
 
</body>

13 优化构建时命令行显示的日志:统计信息stats:

webpack.config.js配置文件中

同时使用friendly-errors-webpack-plugin可以显示构建后不同的状态,成功绿色,警告黄色,报错红色

module.exports = {

plugins:[ new FriendlyErrorsWebpackPlugin() ]

stats:'errors-only' // 表示只有发生错误输出日志

}

<think>好的,我现在需要帮助用户解决如何正确配置cross-env和Webpack开发服务器,以设置BABEL_ENV环境变量并使用自定义的Webpack配置文件。我需要结合用户提供的引用内容,整理出一个清晰的步骤指南。 首先,用户的问题涉及几个关键点:运行Webpack开发服务器、配置Babel环境变量,以及正确使用cross-env。根据引用内容,特别是引用[3]和[4],cross-env的作用是跨平台设置环境变量,这在Windows系统中尤为重要,因为直接使用类似NODE_ENV=development的命令会报错。因此,用户需要在package.json的脚本中使用cross-env来设置环境变量。 接下来,关于Babel环境变量的配置,可能需要通过BABEL_ENV来指定不同的环境配置。根据引用[5],Babel的配置可能与presets有关,而环境变量可以影响Babel的行为。不过用户提到的是设置BABEL_ENV,所以需要确保在脚本中正确传递这个变量。 然后,用户想要使用自定义的Webpack配置文件。通常在Webpack的命令中,可以通过--config参数指定配置文件路径。例如,在引用[1]中,配置了"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js",这说明自定义配置文件的使用方法。 现在需要将这些元素整合起来。用户需要修改package.json中的scripts部分,使用cross-env来设置BABEL_ENV,并运行webpack-dev-server,同时指定自定义的配置文件。例如,脚本可能类似于:"dev": "cross-env BABEL_ENV=development webpack-dev-server --config ./config/webpack.dev.js" 同时,可能需要检查webpack配置文件中是否正确处理了环境变量。根据引用[2],使用webpack.DefinePlugin可以定义全局变量,这可能与Babel的环境变量配置有关联,但BABEL_ENV更可能在Babel的配置文件中使用,比如.babelrc或babel.config.js,根据不同的环境加载不同的预设或插件。 另外,需要注意依赖的安装是否正确。用户需要安装cross-env作为开发依赖,以及webpack-dev-server、webpack-cli等。根据引用[4],安装cross-env的命令是npm install --save-dev cross-env,所以需要确保用户已经正确安装。 可能的错误点包括:拼写错误(比如BABEL_ENV写错),路径错误(自定义配置文件的位置不正确),或者没有正确安装相关依赖。引用[3]中提到,如果删掉cross-env可能在Windows下出错,所以必须保留cross-env以确保跨平台兼容性。 总结步骤应该是:安装cross-env,修改package.json脚本,设置BABEL_ENV,添加webpack-dev-server命令和--config参数,确保配置文件存在且正确,并处理Babel配置中的环境变量。 最后,需要验证配置是否正确,运行npm run dev后,检查是否启动了开发服务器,并且Babel根据BABEL_ENV加载了正确的配置。如果有错误,可能需要检查控制台输出,确认环境变量是否正确传递,配置文件路径是否正确,以及依赖是否安装完整。</think>### 分步配置指南 #### 1. 安装必要依赖 ```bash npm install --save-dev cross-env webpack webpack-cli webpack-dev-server ``` #### 2. 修改 `package.json` 脚本配置 在 `scripts` 字段中添加开发环境命令,使用 `cross-env` 设置 `BABEL_ENV` 环境变量,并指定 Webpack 自定义配置文件: ```json { "scripts": { "dev": "cross-env BABEL_ENV=development webpack-dev-server --config ./webpack.dev.config.js --open" } } ``` - **`cross-env BABEL_ENV=development`**:跨平台设置 `BABEL_ENV` 为 `development`[^1][^3] - **`--config ./webpack.dev.config.js`**:指定自定义 Webpack 配置文件路径 - **`--open`**:自动打开浏览器 #### 3. 创建自定义 Webpack 配置文件 新建 `webpack.dev.config.js` 并配置基础开发环境: ```javascript module.exports = { mode: 'development', entry: './src/index.js', output: { filename: 'bundle.js' }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: [ ['@babel/preset-env', { targets: "defaults" }] ] } } } ] }, devServer: { static: './dist' } }; ``` #### 4. 配置 Babel 环境变量(可选) 在 `.babelrc` 中根据 `BABEL_ENV` 配置不同预设: ```json { "env": { "development": { "presets": ["@babel/preset-env"], "plugins": ["react-hot-reload"] }, "production": { "presets": ["@babel/preset-env"] } } } ``` 通过 `BABEL_ENV=development` 可激活对应环境的配置[^5] #### 5. 验证运行 ```bash npm run dev ``` 成功后会: 1. 自动打开浏览器 2. 控制台显示 "BABEL_ENV: development" 3. 启用 Webpack HMR 热更新功能 ### 关键问题排查点 1. **环境变量未生效**: - 确保 `cross-env` 前缀正确且版本 >=7.0.3 -Webpack 配置中可通过 `process.env.BABEL_ENV` 验证 2. **配置文件加载失败**: ```javascript // 在 webpack 配置中打印验证 console.log('Current BABEL_ENV:', process.env.BABEL_ENV) ``` 3. **Babel 配置不生效**: - 检查 `babel-loader` 是否安装(`npm install babel-loader @babel/core @babel/preset-env`) - 确保 `exclude: /node_modules/` 未错误排除项目文件 ### 进阶配置建议 1. **多环境扩展**: ```json { "scripts": { "dev": "cross-env BABEL_ENV=development NODE_ENV=development webpack-dev-server --config webpack.dev.js", "build:prod": "cross-env BABEL_ENV=production NODE_ENV=production webpack --config webpack.prod.js" } } ``` 2. **全局变量注入**: 使用 `webpack.DefinePlugin` 注入环境变量: ```javascript new webpack.DefinePlugin({ 'process.env.BABEL_ENV': JSON.stringify(process.env.BABEL_ENV) }) ``` : cross-env 的跨平台兼容性解决方案 : webpack-dev-server 与 cross-env 的配合使用 [^5]: Babel 环境变量与 npm 脚本的集成
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值