如何使用Webpack/Gulp编译含liquid标签的.js.liquid文件?
可以通过Gulp或Webpack的自定义配置实现*.js.liquid文件的编译压缩,核心思路是先隔离保护Liquid标签,再完成JS的编译压缩操作,最后还原Liquid标签即可。
方案1:Gulp实现流程
- 依赖安装:执行
npm install gulp gulp-terser gulp-replace gulp-rename --save-dev安装所需工具 - 核心配置逻辑:
- 匹配所有*.js.liquid后缀的文件
- 用正则匹配所有Liquid标签(包括{{ 变量 }}、{% 逻辑块 %}、带空白控制的{%- -%}、{{- -}}等格式),将标签替换为唯一占位符,同时存储标签和占位符的映射关系
- 调用terser对纯JS内容做压缩处理,此时不会涉及Liquid标签,不会出现语法报错
- 压缩完成后,根据映射表将占位符还原为原始Liquid标签
- 重命名输出文件,保留.liquid后缀
- 示例配置片段:
const gulp = require('gulp'); const terser = require('gulp-terser'); const replace = require('gulp-replace'); const rename = require('gulp-rename'); gulp.task('build:js-liquid', () => { const liquidTags = []; return gulp.src('src/js/*.js.liquid') // 替换Liquid标签为占位符 .pipe(replace(/({[{%]-?[\s\S]*?-?[%}]})/g, (match) => { const index = liquidTags.length; liquidTags.push(match); return `__LIQUID_${index}__`; })) // 压缩JS .pipe(terser({ compress: { drop_console: false // 可根据需求调整压缩规则 } })) // 还原Liquid标签 .pipe(replace(/__LIQUID_(\d+)__/g, (match, index) => { return liquidTags[parseInt(index, 10)]; })) .pipe(rename({ extname: '.js.liquid' })) .pipe(gulp.dest('dist/assets')); });
方案2:Webpack实现流程
- 依赖安装:执行
npm install terser-webpack-plugin string-replace-loader babel-loader --save-dev安装所需工具 - 核心配置逻辑:
- 在webpack配置的module.rules中新增.js.liquid文件的匹配规则
- 执行顺序从下到上:先用string-replace-loader把Liquid标签替换为占位符,再走babel编译逻辑,最后再用string-replace-loader还原Liquid标签
- 配置TerserPlugin处理JS压缩,排除占位符相关的语法校验
- 示例配置片段:
const TerserPlugin = require('terser-webpack-plugin'); let liquidTags = []; module.exports = { entry: './src/app.js.liquid', output: { filename: 'app.js.liquid', path: __dirname + '/dist/assets' }, module: { rules: [ { test: /\.js\.liquid$/, use: [ // 最后一步:还原Liquid标签 { loader: 'string-replace-loader', options: { search: /__LIQUID_(\d+)__/g, replace: (match, index) => liquidTags[parseInt(index, 10)] } }, // 第二步:编译JS { loader: 'babel-loader' }, // 第一步:替换Liquid标签为占位符 { loader: 'string-replace-loader', options: { search: /({[{%]-?[\s\S]*?-?[%}]})/g, replace: (match) => { const index = liquidTags.length; liquidTags.push(match); return `__LIQUID_${index}__`; } } } ] } ] }, optimization: { minimizer: [new TerserPlugin({ test: /\.js(\.liquid)?$/i })] } };
注意事项
- 转义用的正则需要覆盖所有Liquid语法场景,避免遗漏标签导致压缩时出现语法报错
- Liquid标签替换必须在JS编译压缩之前完成,标签还原必须在压缩之后执行,不能打乱顺序
- 如果Liquid标签直接用在JS表达式中,建议将标签包裹在引号内作为字符串使用,比如
const currency = '{{ shop.currency }}';是合法写法,不要写const currency = {{ shop.currency }};,否则会出现JS语法错误
替代方案(无需自定义配置)
如果不想写额外的标签转义逻辑,可以将JS代码和Liquid变量拆分:
- 在主题的全局liquid模板(比如theme.liquid)的头部添加script标签,把所有需要用到的Liquid变量挂载到window全局对象上,示例:
<script> window.themeGlobal = { shopName: '{{ shop.name }}', cartUrl: '{{ routes.cart_url }}', productId: '{{ product.id | default: 0 }}' } </script>
- 原有JS文件去掉.liquid后缀,改为纯JS文件,直接调用全局变量即可,比如
console.log(window.themeGlobal.shopName),之后可以用常规的Webpack/Gulp流程正常编译压缩纯JS文件,不需要处理Liquid标签。
内容的提问来源于stack exchange,提问作者bryanyi
相关产品推荐
相关产品推荐

