搭建一个简单的webpack(四)

1、解决本地资源(css、js)打包报错问题【看dist文件夹下的css文件夹和js文件夹】

webpack在npm run dev运行时会因为检测不到pulic文件夹下的css文件和js文件而报错。

npm install copy-webpack-plugin -D

修改webpack.config.js文件的配置

const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
    
    
  plugins: [
    //plugins数组放所有的webpack插件
    new CopyWebpackPlugin([
      {
    
    
        from: "public/js/*.js",
        to: path.resolve(__dirname, "dist", "js"),
        //flatten属性只会拷贝文件,不会把文件路径也拷贝上
        flatten: true
      },
      {
    
    
        from:'public/css/*.css',
        to:path.resolve(__dirname,'dist','css'),
        flatten:true
      }
    ],{
    
    
    //忽略某个文件
      ignore:['another.css','another.js']
    })
  ],
}

其中如果把css的flatten设置为false,npm run dev会出现如下报错:Refused to apply style from 'http://localhost:8000/css/base.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.npm run build会生成这样一个dist文件夹:
在这里插入图片描述
如果把js的flatten设置为false,npm run dev会出现如下报错:GET http://localhost:8000/js/base.js net::ERR_ABORTED 404 (Not Found)npm run build会生成这样一个dist文件夹:
在这里插入图片描述
所以flatten属性必须设置为true

2、抽离CSS【看dist文件夹下的css1文件夹】

安装mini-css-extract-plugin

npm install mini-css-extract-plugin -D

修改webpack.config.js文件的配置

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
    
    
  module: {
    
    
    rules: [
      {
    
    
        test: /\.(le|c)ss$/,
        use: [
          //替换之前的style-loader
          MiniCssExtractPlugin.loader,
          // "style-loader",
          "css-loader",
          {
    
    
            loader: "postcss-loader",
            options: {
    
    
              plugins: function() {
    
    
                return [
                  //overrideBrowserslist被存储到.browserslistrc文件夹下
                  require("autoprefixer")()
                ];
              }
            }
          },
          "less-loader"
        ],
        exclude: /node_modules/
      }
    ]
  },
  plugins: [
    //plugins数组放所有的webpack插件
    new MiniCssExtractPlugin({
    
    
      filename: "css1/[name].css",
      // publicPath:'../'
    })
  ],
}

这样在public文件夹下的css文件和js文件就被抽离出来了。css文件夹存放的是public文件夹下的css文件。css1文件夹存放的是src文件夹下的css文件。js文件夹存放的是public文件夹下的js文件
在这里插入图片描述
把css文件抽离出来之后,还要对css文件进行压缩

npm install optimize-css-assets-webpack-plugin -D

修改webpack.config.js文件的配置

const OptimizeCssPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
    
    
  module: {
    
    
    rules: [
      {
    
    
        test: /\.(le|c)ss$/,
        use: [
          {
    
    
            loader: MiniCssExtractPlugin.loader,
            options: {
    
    
              hmr: isDev,
              reloadAll: true
            }
          },
          //替换之前的style-loader
          // MiniCssExtractPlugin.loader,
          // "style-loader",
          "css-loader",
          {
    
    
            loader: "postcss-loader",
            options: {
    
    
              plugins: function() {
    
    
                return [
                  //overrideBrowserslist被存储到.browserslistrc文件夹下
                  require("autoprefixer")()
                ];
              }
            }
          },
          "less-loader"
        ],
        exclude: /node_modules/
      },
     
    ]
  },
  plugins: [
    //plugins数组放所有的webpack插件
    new OptimizeCssPlugin()
  ],
}

npm run build之后,css1文件下的main.css文件就被压缩了

body{
    
    transition:all 2s}div{
    
    background-color:red;color:green;font-size:20px;height:200px}

3、ProvidePlugin

ProvidePlugin不需要进行npm安装,因为它是webpack的内置插件。ProvidePlugind的作用就是无需进行importrequire对库进行引入。
下面的代码示例引入了Vue、React、jQuery、map

module.exports = {
    
    
  plugins: [
    //plugins数组放所有的webpack插件
    new webpack.ProvidePlugin({
    
    
      //Vue的配置必须有default,因为vue.em.js是靠export default导出的
      Vue: ["vue/dist/vue.esm.js", "default"],
      //React不需要default,因为React是靠module.export导出的
      React: "react",
      Component: ["react", "Component"],
      $: "jquery",
      _map: ["lodash", "map"]
    })
  ],

如果项目启动了 eslint ,还得在package-lock.json文件的globals添加react或vue等框架属性:

    "globals": {
    
    
      "version": "11.12.0",
      "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
      "dev": true,
      "React":true,
      "Vue":true
    },

注:不建议过多使用ProvidePlugin,因为这样会减慢打包的速度、增加打包的负担。

4、webpack热更新

webpack热更新是指当我们修改了部分代码,但是我们不想看到页面全部重新加载的更新方法。
首先修改webpack.config.js文件的配置

module.exports = {
    
    
  devServer: {
    
    
  //...
    hot:true
  },
  plugins: [
      new webpack.HotModuleReplacementPlugin()
  ]
}

修改入口文件

if (module && module.hot) {
    
    
  module.hot.accept(['./js/base.js'], () => {
    
    
    render()
  })
}

这样的话js文件夹下的base.js文件发生改变时,整个页面不会全部重新加载。

5、多入口应用

首先先新建一个login.html文件(public文件夹)和一个login.js文件(src文件夹)。
然后修改webpack.config.js文件的配置

module.exports = {
    
    
  entry: {
    
    
    index:'./src/index.js',
    login:'./src/login.js'
  },
  plugins: [
    new HtmlWebpackPlugin({
    
    
      template: "./public/index.html",
      filename: "index.html",
      minify: {
    
    
        removeAttributeQuotes: false,
        collapseWhitespace: false
      },
      config: config.template
    }),
    new HtmlWebpackPlugin({
    
    
      template: "./public/login.html",
      filename: "login.html",
      minify: {
    
    
        removeAttributeQuotes: false,
        collapseWhitespace: false
      },
      config: config.template
    }),
  ]
}

npm run build之后,index.html和login.html分别都引入了css1文件夹下的css文件和bundle.7dce74.js(两次)。
因此还需要再次修改webpack.config.js文件的配置。HtmlWebpackPlugin 插件提供了一个 chunks 的参数,该参数可以接受一个数组,配置该参数会将数组中指定的css文件引入到html文件中。

module.exports = {
    
    
  entry: {
    
    
    index:'./src/index.js',
    login:'./src/login.js'
  },
  plugins: [
    new HtmlWebpackPlugin({
    
    
      template: "./public/index.html",
      filename: "index.html",
      minify: {
    
    
        removeAttributeQuotes: false,
        collapseWhitespace: false
      },
      config: config.template,
      chunks:['login']
    }),
    new HtmlWebpackPlugin({
    
    
      template: "./public/login.html",
      filename: "login.html",
      minify: {
    
    
        removeAttributeQuotes: false,
        collapseWhitespace: false
      },
      config: config.template,
      chunks:['login']
    }),
  ]
}

6、resolve 配置modules

webpack 内置 JavaScript 模块化语法解析功能,默认会采用模块化标准里约定好的规则去寻找,但我们可以根据自己的需要修改默认规则。

//webpack.config.js
module.exports = {
    
    
    //....
    resolve: {
    
    
        modules: ['./src/components', 'node_modules']
    }
}

这样配置以后,当我们 import FoodList from 'FoodList'时,首先会去寻找 ./src/components是否有FoodList组件;如果在 ./src/components 下找不到的话,就会到 node_modules 下寻找。

7、区别公共、开发、生产环境

之前的学习提到过,需要区分开发环境还是生产环境,我们可以根据 process.env.NODE_ENV 进行区分配置。
其实我们可以创建多个配置文件,如: webpack.base.js、webpack.dev.js、webpack.prod.js

  • webpack.base.js:定义公共的配置。
  • webpack.dev.js:定义开发环境的配置。
  • webpack.prod.js:定义生产环境的配置。

8、定义环境变量

我们在开发环境中会使用本地域名生产环境中使用线上域名,我们可以在 webpack 定义环境变量,方便在代码运行中知道是开发环境还是生产环境。使用 webpack 内置插件 DefinePlugin 来定义环境变量。

module.exports = {
    
    
  plugins: [
    new webpack.DefinePlugin({
    
    
      DEV: JSON.stringify("dev"),
      FLAG: "true"
    })
  ]
}

在index.js入口文件中写到:

if (DEV === "dev") {
    
    
  console.log("开发环境");
} else {
    
    
  console.log("生产环境");
}

当我们运行npm run dev时,会打印出“开发环境”
在这里插入图片描述

9、webpack跨域

新建一个server.js文件

let express = require("express");
let app = express();

app.get("/user", (req, res) => {
    
    
  res.json({
    
     name: "范梦羽" });
});
app.listen(4000);

修改index.js文件

fetch("/api/user")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(err => console.log(err));

然后修改webpack.config.js文件的配置

module.exports = {
    
    
devServer: {
    
    
    proxy: {
    
    
      "/api": {
    
    
        target: "http://localhost:4000",
        pathRewrite: {
    
    
        //在配置代理时,去掉/api
          api: ""
        }
      }
    }
  },
}

最后在Network中可以看到打印出来的数据
在这里插入图片描述

10、前端模拟数据

  • (1)简单模拟数据

修改webpack.config.js文件的配置

module.exports = {
    
    
devServer: {
    
    
    before(app) {
    
    
      app.get("/sex", (req, res) => {
    
    
        res.json({
    
     sex: "girl" });
      });
    }
  },
}

修改index.js文件

fetch("sex")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(err => console.log(err));

在这里插入图片描述

  • (2)moke数据

先安装mocker-api

npm install mocker-api -D

修改webpack.config.js文件的配置

const apiMocker = require("mocker-api");
module.exports = {
    
    
devServer: {
    
    
    before(app) {
    
    
      apiMocker(app, path.resolve("./mock/mocker.js"));
    }
  },
}

新建moke.js

module.exports = {
    
    
  "GET /age": {
    
     age: 21 },
  "POST /login/account": (req, res) => {
    
    
    const {
    
     password, username } = req.body;
    if (password === "888888" && username === "admin") {
    
    
      return res.send({
    
    
        status: "ok",
        code: 0,
        token: "sdfsdfsdfdsf",
        data: {
    
     id: 1, age: 21 }
      });
    } else {
    
    
      return res.send({
    
     status: "error", code: 403 });
    }
  }
};

修改index.js

fetch("/login/account", {
    
    
  method: "POST",
  headers: {
    
    
    Accept: "application/json",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    
    
    username: "admin",
    password: "888888"
  })
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(err => console.log(err));

在这里插入图片描述

详情可查看我搭建的webpackTest

猜你喜欢

转载自blog.csdn.net/qq_44997147/article/details/105148474