目前nuxt项目想使用partytown,nuxt3 可以直接安装Nuxtjs/partytown来安装partytown。nuxt2 2.17.0以上版本可以通过安装nuxtjs/bridge再安装nuxtjs/partytown实现partytown的安装。
但是如果nuxt版本在2.17.0以下,并没有找到适配插件,这里我化用了nuxtjs/partytown写了相关代码,以安装partytown。
1.安装builder.io/partytown。
方法:
- 直接在项目package.json的dependencies配置里加上条目:"@builder.io/partytown": "^0.6.0"
- 执行命令行yarn install.
2.目录modules,新建模块partytown,新建文件夹index.js
index.js文件内容:
import { join } from 'path';
import { promises } from 'fs';
import { genObjectFromRawEntries } from 'knitwork';
import { defineNuxtModule, isNuxt2 } from '@nuxt/kit';
import { libDirPath, copyLibFiles } from '@builder.io/partytown/utils';
import { withLeadingSlash, withTrailingSlash, withoutTrailingSlash } from 'ufo';
import path from 'path';
const module = defineNuxtModule({
meta: {
name: "@nuxtjs/partytown",
configKey: "partytown"
},
// partytown文件路径。partytown官方推荐将插件lib目录下文件复制到自己的代码里,
// 或者放到CDN上,直接放到CDN上我没试过,如果复制到自己的文件夹下,比如Nuxt2项目的static目录下partytown文件,lib配置应该为'/partytown/',下面这个配置,用的是读取插件里的目录
defaults: (nuxt) => ({
debug: false,
forward: [],
lib: "~partytown"
}),
async setup(options, nuxt) {
const fns = ["resolveUrl", "get", "set", "apply"];
options.lib = withLeadingSlash(withTrailingSlash(options.lib));
const rawConfig = Object.entries(options).map(
([key, value]) => [key, fns.includes(key) ? value : JSON.stringify(value)]
);
const renderedConfig = genObjectFromRawEntries(rawConfig).replace(/\s*\n\s*/g, " ");
const partytownSnippet = await promises.readFile(path.resolve(__dirname, './partytown.js'), "utf-8"); //读取partytown会展示在页面内的Snippet代码。这块代码可以继续使用nuxtjs/partytown原生的代码,那个读取的是插件里的partytown.js。
if (isNuxt2()) {
const nuxt2Options = nuxt.options;
nuxt2Options.head = nuxt2Options.head || {};
nuxt2Options.head.__dangerouslyDisableSanitizersByTagID = nuxt2Options.head.__dangerouslyDisableSanitizersByTagID || {};
nuxt2Options.head.__dangerouslyDisableSanitizersByTagID.partytown = ["innerHTML"];
nuxt2Options.head.__dangerouslyDisableSanitizersByTagID["partytown-config"] = ["innerHTML"];
nuxt2Options.head.script.unshift(
{ id: "partytown-config", hid: "partytown-config", innerHTML: `partytown = ${renderedConfig}` },
{ id: "partytown", hid: "partytown", innerHTML: partytownSnippet }
); //将partytown的内容插入页面
// nuxtjs/gtm希望被partytown处理。这是我安装partytown的最主要原因,因为项目安装了google tag manager,且存在多语言多站点环境。所以使用了nuxtjs/gtm,如果项目没有多语言多站点这种要求,可以直接参考partytown官网view page source后看到的gtm安装代码的配置进行配置。官网文档里的写法我没有成功。
// gtm那边又有十几个平台的数据追踪,希望通过partytown把这些数据追踪代码放到web worker工作。
// 但是发现后续这块还得有更多配置,之后处理完毕再进行这块进度。
let HeaderScript =nuxt2Options.head.script;
let gtmScript = nuxt2Options.head.script.find((script) => script.hid === 'gtm-script');
if (gtmScript) {
HeaderScript.splice(HeaderScript.indexOf(gtmScript), 1);
gtmScript.innerHTML = `if(!window._gtm_init){window._gtm_init=1;(function(w,n,d,m,e,p){w[d]=(w[d]==1||n[d]=='yes'||n[d]==1||n[m]==1||(w[e]&&w[e][p]&&w[e][p]()))?1:0})(window,navigator,'doNotTrack','msDoNotTrack','external','msTrackingProtectionEnabled');(function(w,d,s,l,x,y){w[x]={};w._gtm_inject=function(i){w[x][i]=1;w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s);j.crossOrigin='true';j.async=true;j.type='text/partytown';j.src='https://www.googletagmanager.com/gtm.js?id='+i;f.parentNode.insertBefore(j,f);window.dispatchEvent(new CustomEvent('ptupdate'));}})(window,document,'script','dataLayer','_gtm_ids','_gtm_inject')}`;
nuxt2Options.head.script.push(gtmScript);
}
nuxt.hook("generate:done", async () => {
await copyLibFiles(join(nuxt.options.generate.dir, options.lib));
});
nuxt.hook("render:setupMiddleware", async (app) => {
const serveStatic = await import('serve-static').then(
(r) => r.default || r
);
// 这块是做什么我没搞懂,其实可以注释掉,如果要使用自己的目录下的文件,这里就需要注释了,不然就会稳定的读取node_modules目录下的插件代码。
app.use(withoutTrailingSlash(withLeadingSlash(options.lib)), serveStatic(libDirPath()));
});
}
}
});
export { module as default };
3.nuxt.config.js文件增加配置
modules:[
...,
'~/modules/partytown', //partytown模块
],
partytown: {
forward: [
'dataLayer.push', // google。这个配置了之后dataLayer.push函数就会在web worker里工作了。
'gtag',
],
debug: process.env.NODE_ENV === 'development', // 开发者模式开启debug模式,不然关闭debug模式
},
head: {
script:[
{
hid: 'gtm',
type: 'text/partytown',
innerHTML: `
window.dataLayer = window.dataLayer || [];
window.gtag = function gtag(){dataLayer.push(arguments);} // gtm里有gtag代码
`
}
],
__dangerouslyDisableSanitizersByTagID: {
gtm: ['innerHTML'],
},
}
4.重启项目,就可以看到gtm代码在partytown线程工作了。