webpack学习笔记,五

1. 如果想编写一个libray的库,代码结构如下:

-library
  -src
     -index.js
     -math.js
     -string.js

math.js

export function add(a, b) {
    return a + b;
}

export function minus(a, b) {
    return a - b;
}

export function multiply(a, b) {
    return a * b;
}

export function division(a, b) {
    return a / b;
}

string.js

import _ from 'lodash';

export function join(a, b) {
    return _.join([a, b], ' ');
}

index.js

import * as math from './math';
import * as string from './string';

export default { math, string }

为了使用下面方式引入:

import library from 'library';
const library = require('library');
require(['library'],function(){

})
<script src="library.js"></script>

需在配置文件中定义:

const path = require('path');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  externals: 'lodash',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'library.js',
    library: 'root',     //在这里定义可以使用 script标签引入 然后注入一个全局吧变量root 使用root.math
    libraryTarget: 'umd' //使用这种定义可以支持 cmd es6 等语法的引入
  }
}

则调用方式是 library.math;

2 如果我们写的库中 已经引入打包过 lodash.js这个库,但是用户也在业务代码中引入了这个库,造成了重复引入。所以要在配置文件中设置 externals: 'lodash', 即 打包时不打包依恋文件

3 结合pwa:

//对线上代码做pwa处理,本地开发不用,所以在生成的dist目录下执行 http-server 服务
首先安装 http-server,然后执行:
"scripts": {
    "start": "http-server dist"
},

npm install workbox-webpack-plugin --save-dev
在线上打包的配置文件中
const WorkboxPlugin = require('workbox-webpack-plugin');
plugins: [
  new WorkboxPlugin.GenerateSW({
    clientsClaim: true,
    skipWaiting: true
  })
],

页面代码中:
console.log('hello, this is dell');

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js') //调用打包生成的 sw.js
      .then(registration => {
        console.log('service-worker registed');
      }).catch(error => {
        console.log('service-worker register error');
      })
  })
}

具体:

webpack 中使用 workbox 实现 PWA
说明
重要文件版本

“workbox-webpack-plugin”: “^3.0.0”
“webpack”: “^3.11.0”
webpack 提供了 workbox 插件 workbox-webpack-plugin

webpack 中使用
在 production 版本配置中使用

1. 在入口 html 模板中引入
<!DOCTYPE html>
<html >
   <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="ie=edge,chrome=1">
      <title>webpack-react-template</title>
      <!-- 引入 manifest 文件 -->
      <link rel="manifest" href="./manifest.json">
   </head>

   <body>
      <div ></div>
      <script>
        // 进行 service-wroker 注册
        if ('serviceWorker' in navigator) {
            window.addEventListener('load', () => {
                navigator.serviceWorker
                    .register('./service-wroker.js')
                    .then(registration => {
                        console.log('SW registered: ', registration);
                    })
                    .catch(registrationError => {
                        console.log('SW registration failed: ', registrationError);
                    });
            });
        }
      </script>
   </body>

</html>
2. webpack.prod.config.js 中进行 webpack 配置
const WorkboxPlugin = require('workbox-webpack-plugin');

module.exports = merge(baseWebpackConfig, {
    // ... 省略其他配置
    plugins: [
        // ... 省略其他配置

        /*
            这里也可以使用 WorkboxPlugin.InjectManifest({}) 配置
            但是需要 配置 swSrc 指明模板 service-worker 文件
            WorkboxPlugin.GenerateSW({}) 可以直接生成 service-worker 文件
         */
        new WorkboxPlugin.GenerateSW({
            cacheId: 'webpack-pwa', // 设置前缀
            skipWaiting: true, // 强制等待中的 Service Worker 被激活
            clientsClaim: true, // Service Worker 被激活后使其立即获得页面控制权
            swDest: 'service-wroker.js', // 输出 Service worker 文件
            globPatterns: ['**/*.{html,js,css,png.jpg}'], // 匹配的文件
            globIgnores: ['service-wroker.js'], // 忽略的文件
            runtimeCaching: [
                // 配置路由请求缓存
                {
                    urlPattern: /.*\.js/, // 匹配文件
                    handler: 'networkFirst' // 网络优先
                }
            ]
        })
    ]
});
注意:配置路由请求缓存,请看另外一篇文章

3. 转移 manifest.json 以及需要的图片
我这里使用了 copy-webpack-plugin 插件用于文件转移
new CopyWebpackPlugin([
    {
        from: 'src/manifest.json',
        to: 'manifest.json'
    },
    {
        from: 'src/icon.png',
        to: 'static/imgs/icon.png'
    }
]);
4. 编译后生成的 service-worker 文件
importScripts(
    'https://storage.googleapis.com/workbox-cdn/releases/3.0.0/workbox-sw.js'
);

importScripts('/test/precache-manifest.14cde9ce3f3a728b83652a5461e9fd24.js');

workbox.core.setCacheNameDetails({ prefix: 'webpack-pwa' });

workbox.skipWaiting();
workbox.clientsClaim();

self.__precacheManifest = [].concat(self.__precacheManifest || []);
workbox.precaching.suppressWarnings();
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});

workbox.routing.registerRoute(
    /.*\.js/,
    workbox.strategies.networkFirst(),
    'GET'
);

文章来源:

webpack 中使用 workbox 实现 PWA

相关文章 PWA 渐进式网络应用 - 1 - 简介及调试方法

PWA 渐进式网络应用 - 3 - manifest.json 添加应用至桌面

5. devServer 开启代理:

我们在本地开发的时候经常会访问到测试服务器等接口,但是如果写的是相对路径,比如:

axios.get('/react/api/header.json')
.then((res) => {
  console.log(res);
})

就会自动调用 http://localhost:8080/react/api/header.json ;这样就会导致跨域。

所以需要做devserver的代理:

devServer: {
  proxy: {
    '/react/api': 'http://www.dell-lee.com' //如果请求的接口是 react/api 则去 dell-lee.com 域名下去访问该接口
  }
}

如有多个路径需要配置:

devServer: {
  proxy: [{
    context:['/auth','/api'],
    target:'http://localhost:3000'
  }]
}

如果相对根路径进行配置,需要设置index 为空:

devServer: {
  proxy: {
    index:'',
    '/': 'https://www.dell-lee.com'
  }
}

如需更多的代理配置项,需要增加参数:

devServer: {
  proxy: {
    '/react/api': {
      target: 'https://www.dell-lee.com', //如果请求的接口是 react/api 则去 dell-lee.com 域名下去访问该接口
      secure: false,  //如果上面用的是https的话 需要设置secure
      pathRewrite: {
        'header.json': 'demo.json' //如果请求的四header.json 则替换成 demo.json
      },
      changeOrigin: true,//突破原网站对代理的限制
      headers: { //设置请求头
        host: 'www.dell-lee.com',
        cookie:'123'
      }
    }
  }
}

更多配置详见官网文档: https://webpack.js.org/configuration/dev-server

6 devserver 如果不做配置,使用路由跳转页面的时候,比如想访问 localhost:8080/list 这个路径会报错,因为他以为是要访问这个路径,但是是单页面应用,所以需要在devserver中配置:

devServer: {
  historyApiFallback:true
}

这样的话,访问任何的路径(后端服务器没有的路径)都会跳转到 当前的根路径。上线后 需要后端修改ngnix或者apaqi服务器上设置(找不到页面跳转到首页)