【Webpack】NodeJS + Webpack

目的:想要通过npm命令按照我们的规则生成静态资源(webpack4以后还能做到很多性能优化的配置,我所知道的只有css、js分包,以达到资源快速加载快速呈现的效果)。

一、安装webpack

npm install --save-dev webpack
or
npm i webpack -D

webpack 4单独分离出webpack-cli,所以要安装webpack-cli

npm i webpack-cli -D

二、由于build和start都会有相同的配置,所以先搞一个公共配置文件webpack.base.conf.js

'use strict'
const path = require('path');
const utils = require('./utils');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        test:/\.jsx$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['es2015', 'react']
          }
        }
      },
      {
        test: /\.css$/,
        use: [ 'style-loader', 'css-loader' ]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]') // 图片名称也要加随机字符串,避免缓存
        }
      },
    ]
  },
};

utils.js

'use strict'
const path = require('path');

exports.assetsPath = function (_path) {
  return path.posix.join('static', _path)
}

三、配置webpack.dev.conf.js

'use strict'
//onst webpack = require('webpack');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');

const devWebpackConfig = merge(baseWebpackConfig, {
  devtool: 'cheap-module-eval-source-map', // 此选项控制是否生成,以及如何生成 source map
})

module.exports = devWebpackConfig

devtool的比较

 

详见https://www.webpackjs.com/configuration/devtool/ 

四、运行npm run start

package的script配置,通过webpack-dev-server实现自动监听并允许webpack

"start": "webpack-dev-server --config build/webpack.dev.conf.js",

报错:

Module not found: Error: Can't resolve 'fs' in 'D:\pro\ReactGame\node_modules\destroy'

于是安装了fs,再运行,还是一样的报错

参考了文章https://blog.csdn.net/flitrue/article/details/78055738

在webpack.base.conf.js添加配置

  node: {
    fs: 'empty',
  }

再次运行,报错:

Module not found: Error: Can't resolve 'net' in 'D:\pro\ReactGame\node_modules\express\lib'

那就在webpack.base.conf.js再添加配置

  node: {
    fs: 'empty',
    net: 'empty',
  }

try again,报错:

TypeError: merge is not a function

原因:merge引入方式不对,改成

const { merge } = require('webpack-merge');

终于启动不报错了。

五、配置webpack.prod.conf.js

'use strict'
const baseWebpackConfig = require('./webpack.base.conf');
const { merge } = require('webpack-merge');
const path = require('path');
const utils = require('./utils');
const webpack = require('webpack');
const ENV = process.env;

const webpackConfig = merge(baseWebpackConfig, {
  mode: 'production',
  devtool: '#source-map',
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    /*
     * chunkFilename用来打包require.ensure方法中引入的模块,如果该方法中没有引入任何模块则不会生成任何chunk块文件
     * 比如在main.js文件中,require.ensure([],function(require){alert(11);}),这样不会打包块文件
     * 只有这样才会打包生成块文件require.ensure([],function(require){alert(11);require('./greeter')})
     * 或者这样require.ensure(['./greeter'],function(require){alert(11);})
     * chunk的hash值只有在require.ensure中引入的模块发生变化,hash值才会改变
     * 注意:对于不是在ensure方法中引入的模块,此属性不会生效,只能用CommonsChunkPlugin插件来提取
     * */
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') // chunkFilename用来打包require.ensure方法中引入的模块
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': '"production"'
    }),
    new webpack.HashedModuleIdsPlugin(),
  ]
})

if (ENV.npm_config_report || ENV.npm_config_a) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

六、运行npm run build

本来我用UglifyJs压缩js,但是最新版uglifyjs-webpack-plugin@2.2.0并不支持es6语法,github有给出说明:

所以在webpack.base.conf.js中配置

optimization: { // webpack 优化
    minimize: true,
    minimizer: [new TerserPlugin({
      terserOptions: {
        mangle: true, // 混淆,默认也是开的,mangle也是可以配置很多选项的,具体看后面的链接
        compress: {
          drop_console: true, // 传true就是干掉所有的console.*这些函数的调用.
          drop_debugger: true, // 干掉那些debugger;
          pure_funcs: ['console.log'] // 如果你要干掉特定的函数比如console.info ,又想删掉后保留其参数中的副作用,那用pure_funcs来处理
        }
      }
    })],
}

 

七、最终配置

package.json

{
  "name": "reactgame",
  "version": "1.0.0",
  "description": "2048",
  "main": "src/index.js",
  "scripts": {
    "start": "webpack-dev-server --config build/webpack.dev.conf.js",
    "build": "node build/build.js"
  },
  "keywords": [
    "myKeywords"
  ],
  "author": "Abby",
  "license": "ISC",
  "dependencies": {
    "ejs": "^3.1.5",
    "express": "^4.17.1",
    "fs": "0.0.1-security",
    "path": "^0.12.7",
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "devDependencies": {
    "chalk": "^4.1.0",
    "extract-text-webpack-plugin": "^4.0.0-beta.0",
    "ora": "^5.1.0",
    "rimraf": "^3.0.2",
    "supervisor": "^0.12.0",
    "terser-webpack-plugin": "^4.1.0",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0",
    "webpack-merge": "^5.1.3"
  }
}

utils.js

'use strict'
const path = require('path');

exports.assetsPath = function (_path) {
  return path.posix.join('static', _path)
}

webpack.base.conf.js

'use strict'
const path = require('path');
const utils = require('./utils');
const TerserPlugin = require('terser-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        test:/\.jsx$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['es2015', 'react']
          }
        }
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({    //css的提取
          fallback: "style-loader",
          use: "css-loader"
        })
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
    ]
  },
  optimization: { // webpack 优化
    minimize: true,
    minimizer: [new TerserPlugin({
      terserOptions: {
        mangle: true, // 混淆,默认也是开的,mangle也是可以配置很多选项的,具体看后面的链接
        compress: {
          drop_console: true, // 传true就是干掉所有的console.*这些函数的调用.
          drop_debugger: true, // 干掉那些debugger;
          pure_funcs: ['console.log'] // 如果你要干掉特定的函数比如console.info ,又想删掉后保留其参数中的副作用,那用pure_funcs来处理
        }
      }
    })],
    splitChunks: { // 分包
      chunks: "all",
      minSize: 100000, // 模块的最小体积
      minChunks: 1, // 模块的最小被引用次数
      maxAsyncRequests: 5, // 按需加载的最大并行请求数
      maxInitialRequests: 3, // 一个入口最大并行请求数
      automaticNameDelimiter: '~', // 文件名的连接符
      name: true,
      maxSize: 500000, // 模块的最小体积
      cacheGroups: { // 缓存组
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  },
  node: {
    fs: 'empty',
    net: 'empty',
  }
};

webpack.dev.conf.js

'use strict'
//onst webpack = require('webpack');
const { merge } = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');

const devWebpackConfig = merge(baseWebpackConfig, {
  
devtool: 'cheap-module-eval-source-map',
// devServer: {
  //   //hot: true,
  // },
})

module.exports = devWebpackConfig

webpack.prod.conf.js

'use strict'
const baseWebpackConfig = require('./webpack.base.conf');
const { merge } = require('webpack-merge');
const path = require('path');
const utils = require('./utils');
const webpack = require('webpack');
const ENV = process.env;

const webpackConfig = merge(baseWebpackConfig, {
  mode: 'production',
  devtool: '#source-map',
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') // chunkFilename用来打包require.ensure方法中引入的模块
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': '"production"'
    }),
    new webpack.HashedModuleIdsPlugin(),
  ]
})

if (ENV.npm_config_report || ENV.npm_config_a) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

 

posted on 2020-09-04 16:31  WhoLovesAbby  阅读(429)  评论(0)    收藏  举报