webpack完整记录

Posted haliofwu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webpack完整记录相关的知识,希望对你有一定的参考价值。

碎碎念:
之前一直在csdn.总觉得csdn氛围不太好,但是因为懒嘛,一直没有迁移.今天波特问我,是否可将我的csdn账号借给他下点东西.我记得我csdn好几千积分的.结果一看,现在积分不能下载了,要靠c币.c币是什么呢?一个c币=300阅读量.这就算了,还有过期机制.一段时间没用,就给清零了…这已经强制大家充币赚钱了…所以,果然是要倒闭了么.

正文

  • webpack入门文章

webpack入坑之旅(一)不是开始的开始

webpack入坑之旅(二)loader入门

webpack.config入门

webpack入坑之旅(四)扬帆起航

webpack编译流程漫谈

>[强烈推荐](https://segmentfault.com/a/1190000005089993?utm_source=tuicool&utm_medium=referral)

  • webpack-dev-server

从名字就可以看出来是webpack 在dev阶段的微型服务器;官方文档也说明了,是开发阶段的实时加载;
 这是一个基于Express.js框架开发的web server,默认监听8080端口。server内部调用Webpack,这样做的好处是提供了额外的功能如热更 新“Live Reload”以及热替换“Hot Module Replacement”(即HMR)。

  • webpack原理

  • 一切皆模块

  • 按需加载

从入口文件开始,按照require或者import加载依赖文件;然后分类打包;

开发者模式/生产模式/测试模式
  不同的模式,需要的功能会不一样.因此,一般会分别写成三个不同的config文件;
  
“entry”:值分别是字符串、数组和对象的情况
Enter配置项告诉Webpack应用的根模块或起始点在哪里,它的值可以是字符串、数组或对象。这看起来可能令人困惑,因为不同类型的值有着不同的目的。

像绝大多数app一样,倘若你的应用只有一个单一的入口,enter项的值你可以使用任意类型,最终输出的结果都是一样的。

enter:数组类型
但是,如果你想添加多个彼此不互相依赖的文件,你可以使用数组格式的值。

例如,你可能在html文件里引用了“googleAnalytics.js”文件,可以告诉Webpack将其加到bundle.js的最后。
enter:对象
现在,假设你的应用是多页面的(multi-page application)而不是SPA,有多个html文件(index.html和profile.html)。然后你通过一个对象告诉Webpack为每一个html生成一个bundle文件。

以下的配置将会生成两个js文件:indexEntry.js和profileEntry.js分别会在index.html和profile.html中被引用。
enter:混合类型
你也可以在enter对象里使用数组类型,例如下面的配置将会生成3个文件:vender.js(包含三个文件),index.js和profile.js文件。
output:“path”项和“publicPath”项
output项告诉webpack怎样存储输出结果以及存储到哪里。output的两个配置项“path”和“publicPath”可能会造成困惑。

“path”仅仅告诉Webpack结果存储在哪里,然而“publicPath”项则被许多Webpack的插件用于在生产模式下更新内嵌到css、html文件里的url值。
例如,在localhost(译者注:即本地开发模式)里的css文件中边你可能用“./test.png”这样的url来加载图片,但是在生产模式下“test.png”文件可能会定位到CDN上并且你的Node.js服务器可能是运行在HeroKu上边的。这就意味着在生产环境你必须手动更新所有文件里的url为CDN的路径。

然而你也可以使用Webpack的“publicPath”选项和一些插件来在生产模式下编译输出文件时自动更新这些url。

// 开发环境:Server和图片都是在localhost(域名)下
.image  
  background-image: url('./test.png');
 
// 生产环境:Server部署下HeroKu但是图片在CDN上
.image  
  background-image: url('https://someCDN/test.png');
 

模块加载和链式模块加载
模块加载器是可自由添加的Node模块,用于将不同类型的文件“load”或“import”并转换成浏览器可以识别的类型,如js、Stylesheet等。更高级的模块加载器甚至可以支持使用ES6里边的“require”或“import”引入模块。
例如,把es7/es8转成es5等;

module: 
loaders: [
 test: /\\.js$/, // 匹配.js文件,如果通过则使用下面的loader
 exclude: /node_modules/, // 排除node_modules文件夹
 loader: 'babel' // 使用babel(babel-loader的简写)作为loader
]

链式(管道式)的加载器(从右往左执行)
多个loader可以用在同一个文件上并且被链式调用。链式调用时从右到左执行且loader之间用“!”来分割
例如,假设我们有一个名为“myCssFile.css”的css文件,然后我们想将它的内容使用style标签内联到最终输出的html里边。我们可以使用css-loader和style-loader两个loader来达到目的。

module: 
 loaders: [
  test: /\\.css$/,
  loader: 'style!css' //(short for style-loader!css-loader)
 ]

  1. Webpack在模块颞部搜索在css的依赖项,即Webpack检查js文件是否有“require(‘myCssFile.css’)”的引用,如果它发现有css的依赖,Webpack将css文件交给“css-loader”去处理

  2. css-loader加载所有的css文件以及css自身的依赖(如,@import 其他css)到JSON对象里,Webpack然后将处理结果传给“style-loader”

  3. style-loader接受JSON值然后添加一个style标签并将其内嵌到html文件里
    loader自身的配置:
    模块加载器(loader)自身可以根据传入不同的参数进行配置。

在下面的例子中,我们可以配置url-loader来将小于1024字节的图片使用DataUrl替换而大于1024字节的图片使用url,我们可以用如下两种方式通过传入“limit“参数来实现这一目的:

插件
插件一般都是用于输出bundle的node模块。
这句话的意思是:这个node的插件可以单独输出你想要的js.

例如,uglifyJSPlugin获取bundle.js然后压缩和混淆内容以减小文件体积。

类似的extract-text-webpack-plugin内部使用css-loader和style-loader来收集所有的css到一个地方最终将结果提取结果到一个独立的”styles.css“文件,并且在html里边引用style.css文件。

//webpack.config.js
// 获取所有的.css文件,合并它们的内容然后提取css内容到一个独立的”styles.css“里
var ETP = require("extract-text-webpack-plugin");

module: 
 loaders: [
  test: /\\.css$/, loader:ETP.extract("style-loader","css-loader") 
  ]
,
plugins: [
    new ExtractTextPlugin("styles.css") //Extract to styles.css file
  ]

注意:如果你只是想把css使用style标签内联到html里,你不必使用extract-text-webpack-plugin,仅仅使用css loader和style loader即可:

module: 
 loaders: [
  test: /\\.css$/,
  loader: 'style!css' // (short for style-loader!css-loader)
 ]

知识点:
Loader处理单独的文件级别并且通常作用于包生成之前或生成的过程中。

而插件则是处理包(bundle)或者chunk级别,且通常是bundle生成的最后阶段。一些插件如commonschunkplugin甚至更直接修改bundle的生成方式。

那么以creact-react-app为例,如何配置自己的环境呢:
第一种方式:在package.json的script中添加:


  ...
  "scripts": 
    "eject": "react-scripts eject"//ts 的话应当是 react-scripts-ts eject
  ,
  ...


将node_modules中react-scripts-ts中的配置弹射出来,无法逆转的过程;一旦弹射,在package.json中会增加很多依赖.在目录结构中,也会多出两个文件夹:scripts/config;scripts中是

是开发环境(start.js),生产环境(build.js),测试环境(test.js)的启动文件;

'use strict';
process.env.BABEL_ENV = 'development';
process.env.NODE_ENV = 'development';
process.on('unhandledRejection', err => 
  throw err;
);
require('../config/env')
const fs = require('fs');
const chalk = require('chalk');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const clearConsole = require('react-dev-utils/clearConsole');
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
const 
  choosePort,
  createCompiler,
  prepareProxy,
  prepareUrls,
 = require('react-dev-utils/WebpackDevServerUtils');
const openBrowser = require('react-dev-utils/openBrowser');
const paths = require('../config/paths');
const config = require('../config/webpack.config.dev');
const createDevServerConfig = require('../config/webpackDevServer.config');

const useYarn = fs.existsSync(paths.yarnLockFile);
const isInteractive = process.stdout.isTTY;
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) 
  process.exit(1);

const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
const HOST = process.env.HOST || '0.0.0.0';

if (process.env.HOST) 
  console.log(
    chalk.cyan(
      `Attempting to bind to HOST environment variable: $chalk.yellow(
        chalk.bold(process.env.HOST)
      )`
    )
  );
  console.log(
    `If this was unintentional, check that you haven't mistakenly set it in your shell.`
  );
  console.log(`Learn more here: $chalk.yellow('http://bit.ly/2mwWSwH')`);
  console.log();

choosePort(HOST, DEFAULT_PORT)
  .then(port => 
    if (port == null) 
      // We have not found a port.
      return;
    
    const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
    const appName = require(paths.appPackageJson).name;
    const urls = prepareUrls(protocol, HOST, port);
    // Create a webpack compiler that is configured with custom messages.
    const compiler = createCompiler(webpack, config, appName, urls, useYarn);
    // Load proxy config
    const proxySetting = require(paths.appPackageJson).proxy;
    const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
    // Serve webpack assets generated by the compiler over a web sever.
    const serverConfig = createDevServerConfig(
      proxyConfig,
      urls.lanUrlForConfig
    );
    const devServer = new WebpackDevServer(compiler, serverConfig);
    // Launch WebpackDevServer.
    devServer.listen(port, HOST, err => 
      if (err) 
        return console.log(err);
      
      if (isInteractive) 
        clearConsole();
      
      console.log(chalk.cyan('Starting the development server...\\n'));
      openBrowser(urls.localUrlForBrowser);
    );

    ['SIGINT', 'SIGTERM'].forEach(function(sig) 
      process.on(sig, function() 
        devServer.close();
        process.exit();
      );
    );
  )
  .catch(err => 
    if (err && err.message) 
      console.log(err.message);
    
    process.exit(1);
  );

config中是:

各环境下的配置文件;在对应的环境下配置需要的loader或插件即可;
如果不想弹射出来,也可以用覆盖的方式写入:

const fs = require('fs')
const path = require('path');

const target = path.resolve(__dirname, '../node_modules/react-scripts-ts/config/webpack.config.prod.js')
var contents = fs.readFileSync(path.resolve(__dirname, './config.js'), 'utf8');
fs.writeFileSync(target, contents,encoding:'utf8',flag:'w')

对应的启动:

 "start-js": "react-scripts-ts start",
 "start": "node replaceWebpackconfig.js && npm-run-all -p watch-css start-js",

非creact-react-app中的webpack使用方法:


创建server.js.用来建立webpack微服务器,
例如:



require('core-js/fn/object/assign');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const config = require('./webpack.config');

const compiler = webpack(config);
new WebpackDevServer(compiler, config.devServer)
.listen(8080, '0.0.0.0', (err) => 
  if (err) 
    console.log(err);
  
);

在主目录下创建webpack.config.js,在其中规定不同命令行加载的真正的webpack的option在哪里;
不要忘记在package.json中添加:

 "start": "node server.js --env=dev",

启动server时,根据env的参数调用对应的config.即可.

以上是关于webpack完整记录的主要内容,如果未能解决你的问题,请参考以下文章

webpack配合vue.js实现完整的单页面demo

webpack 4 入坑及爬坑记录

瑞芯微RV1126 修改串口的波特率学习笔记

瑞芯微RV1126 修改串口的波特率学习笔记

antd在webpack里面的配置

前端短讯webpack v4.6.0 发布